Skip to content

Handle NaN in json_int() (undefined double->int cast)#541

Open
gigioneggiando wants to merge 1 commit into
antirez:mainfrom
gigioneggiando:fix/json-int-nan
Open

Handle NaN in json_int() (undefined double->int cast)#541
gigioneggiando wants to merge 1 commit into
antirez:mainfrom
gigioneggiando:fix/json-int-nan

Conversation

@gigioneggiando

Copy link
Copy Markdown

Summary

json_number() is a thin strtod() wrapper, which per C99 accepts "NaN" and "Infinity". In json_int() the two clamps v < 0 and v > INT_MAX are both false for NaN (every comparison against NaN is false), so a NaN value reaches the (int)v cast, which is undefined behavior for NaN (on x86-64 it yields INT_MIN).

So a request field like {"max_tokens": NaN} produces an out-of-range integer conversion rather than being rejected/clamped.

Fix

Replace if (v < 0) v = 0; with if (!(v >= 0)) v = 0;, which folds NaN (and negatives) to 0. +Infinity / -Infinity remain handled by the existing clamps. One-line change, no new dependency.

Verification

Built under UBSan with -fsanitize=float-cast-overflow, driving the real json_int("NaN"):

  • before: runtime error: nan is outside the range of representable values of type 'int'.
  • after: returns 0, no trap.

Low severity (no memory corruption), found during a coordinated security review of ds4; a standalone offline PoC is available on request.

json_number() is a thin strtod() wrapper, which per C99 accepts "NaN" and
"Infinity". In json_int() the clamps `v < 0` and `v > INT_MAX` are both
false for NaN (every NaN comparison is false), so NaN reaches the (int)v
cast, which is undefined behavior (on x86-64 it yields INT_MIN).

Replace `if (v < 0)` with `if (!(v >= 0))`, which folds NaN and negatives
to 0; +/-Infinity are still handled by the two clamps.
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.

1 participant