Skip to content

Uncaught json::parse_error exception crashes process on malformed model files #1395

@professor-moody

Description

@professor-moody

Git commit

$git rev-parse HEAD
87ecb95

Operating System & Version

Fedora 43

GGML backends

HIP

Command-line arguments used

sd -m crash.bin -p "test"

Steps to reproduce

Steps to reproduce

  1. Create a 16-byte test file that looks like a SafeTensors header but contains invalid JSON:
import struct
# 8-byte LE header size (=4), then 4 bytes of non-JSON, then padding
buf = struct.pack('<Q', 4) + b'XXXX' + b'YYYY'
with open('crash.bin', 'wb') as f:
    f.write(buf)
  1. Run: sd -m crash.bin -p "test"

The crash occurs during format auto-detection in is_safetensors_file(), so any file whose first 8 bytes produce a header size in the accepted range (3 to filesize−1) will trigger it — even files intended for other formats (GGUF, checkpoint).

What you expected to happen

What you expected to happen

The process should reject the malformed file gracefully and return an error, since is_safetensors_file() already has an is_discarded() check for this case.

What actually happened

What actually happened

The process crashes with std::terminate()abort().

Logs / error messages / stack trace

Logs / error messages / stack trace

terminate called after throwing an instance of 'nlohmann::json_abi_v3_11_2::detail::parse_error'
  what(): [json.exception.parse_error.101] parse error at line 1, column 1:
          syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal
Aborted (core dumped)

Additional context / environment details

Additional context / environment details

Root causesrc/model.cpp:318:

nlohmann::json header_ = nlohmann::json::parse(header_buf.data());  // throws on invalid JSON
if (header_.is_discarded()) {  // dead code — never reached
    return false;
}

Suggested two-line fix — pass false for allow_exceptions so the existing error handling works:

--- a/src/model.cpp
+++ b/src/model.cpp
@@ -315,7 +315,7 @@
-    nlohmann::json header_ = nlohmann::json::parse(header_buf.data());
+    nlohmann::json header_ = nlohmann::json::parse(header_buf.data(), nullptr, false);

@@ -511,7 +511,7 @@
-    nlohmann::json header_ = nlohmann::json::parse(header_buf.data());
+    nlohmann::json header_ = nlohmann::json::parse(header_buf.data(), nullptr, false);
  • x86_64, clang 21.1.8
  • Reproduces on both sanitizer and release builds
  • Found via fuzz testing with crafted model files

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions