Skip to content

generate: reject a NUL character inside a JSON string - #181

Merged
giuseppe merged 1 commit into
containers:mainfrom
kolyshkin:reject-nul
Oct 19, 2026
Merged

giuseppe merged 1 commit into
containers:mainfrom
kolyshkin:reject-nul

Conversation

@kolyshkin

Copy link
Copy Markdown
Collaborator

JSON allows \u0000 inside a string, and json-c keeps it, but the parsed value is copied with strdup(), so everything after the first NUL is silently dropped:

"options": ["nosuid\u0000,noexec"]

parses without any error and yields a single nosuid option, with noexec gone. The same happens to every string in the document: paths, process arguments and environment, hook paths, annotations. A runtime has no way to notice, as by the time it sees the value it is a perfectly valid, if shorter, C string. This was reported against crun in containers/crun#2105 (runc and youki reject such a config).

This adds dup_json_string(), which copies a JSON string, rejecting it if its JSON length does not match its C string length, and uses it for every string the generated code reads (165 call sites in the runtime and image specs), plus the string values of json_map_string_string and json_map_int_string.

Object keys are not covered: json-c truncates them at the first NUL by itself, so there is nothing left to check by the time libocispec sees them.

tests/test-17.c covers a plain string, a string inside an array of objects, arrays of strings, and a string map; without the change all six cases fail.

Verified: make check 17/17, make distcheck.

JSON allows \u0000 inside a string, and json-c keeps it, but the parsed
value is copied with strdup(), so everything after the first NUL is
silently dropped:

    "options": ["nosuid\u0000,noexec"]

parses without any error and yields a single "nosuid" option, with
"noexec" gone.  The same happens to every string in the document:
paths, process arguments and environment, hook paths, annotations.
A runtime has no way to notice, as by the time it sees the value it is
a perfectly valid, if shorter, C string.

Add dup_json_string(), which copies a JSON string, rejecting it if its
JSON length does not match its C string length, and use it for every
string the generated code and the string maps read.

Note that json-c truncates object keys at the first NUL by itself, so
those cannot be checked here.

Add tests/test-17.c.

Reported-in: containers/crun#2105
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
@kolyshkin
kolyshkin requested a review from giuseppe October 19, 2026 05:22

@giuseppe giuseppe left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@giuseppe
giuseppe merged commit 65e2c08 into containers:main Oct 19, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants