✓ProveIt
Examples / Report #3400831 Saved analysis

CURLX_SET_BINMODE(NULL) can call fileno(NULL) and cause undefined behavior / crash

curl · 2025-10-278.6s analysis · $0.010 in model calls

What the report claims

Calling CURLX_SET_BINMODE(NULL) leads to an unguarded call to fileno(NULL) causing undefined behavior or crash.

Compare with curl's recorded outcome

Labeled AI slop

curl's maintainer lists this report as AI slop

Shown for comparison after analysis. The pipeline did not see this label.

ProveIt's finding

References do not check out

Key code references could not be verified in the targeted curl version.

curl policy: API misuse
Why this finding?
  • The report itself states 'This is non-security; public PR is appropriate.'
  • The project policy's 'API misuse' section says issues triggered by using the API in undocumented/unsupported ways are not security problems.
  • The macro expects a valid FILE*; passing NULL is API misuse, not a vulnerability.
  • The location claim (tool_binmode.h) is factually incorrect — the macro is in lib/curlx/binmode.h.
How this analysis ran 5 claims · 4 citations verified

Checked against curl master on 2025-10-27 (ab20bb47cf4c). Dev evaluation split. Citation verification checks that a referenced line was in the evidence; it does not prove the model interpreted it correctly.

1 · Grounding
not grounded
no model · 6 references checked out, 1 did not
2 · Claims
NVIDIA-Nemotron-3-Nano-30B-A3B
5 claims · 1722 tokens · $0.0002
3 · Evidence
3 code snippets
real curl source at ab20bb47cf4c
4 · Judgment
Nemotron-3-Ultra-550b-a55b
5866 tokens · 6.1s · $0.0094
5 · Receipts
4 of 6 citations verified
every citation must point at code the judge was shown
Review a draft reply to the reporter

Edit and verify before sending.

Thank you for the report and the reproducible test case. The macro CURLX_SET_BINMODE in lib/curlx/binmode.h does indeed call fileno(stream) without a NULL check, so passing NULL invokes undefined behavior. However, this falls under our 'API misuse' policy: the macro is documented to take a valid FILE* stream, and passing NULL is not a supported use case. We do not treat such NULL-dereference crashes from API misuse as security vulnerabilities. We may still accept a robustness fix (e.g., a NULL guard) as a regular bug fix via a public PR.

Inspect all claims and source code 5 claims · 3 code excerpts

Report claims

C1flaw supported

Calling CURLX_SET_BINMODE(NULL) results in an unguarded call to fileno(NULL)

Read the reasoning

The macro expands directly to fileno(stream) with no guard. If stream is NULL, fileno(NULL) is called, which is undefined behavior per POSIX.

C2location contradicted

in tool_binmode.h

Read the reasoning

The report states the macro is in tool_binmode.h, but the deterministic check confirms no such file exists in curl's history. The macro resides in lib/curlx/binmode.h.

deterministic check lib/curlx/binmode.h:31
C3trigger supported

passing NULL as the stream argument to CURLX_SET_BINMODE

Read the reasoning

The trigger is simply passing NULL as the argument, which the macro does not validate.

C4impact supported

may crash the process or cause undefined behavior

Read the reasoning

Calling fileno with a NULL FILE* is undefined behavior; the report correctly identifies the consequence.

C5reproduction supported

run the provided test program that calls CURLX_SET_BINMODE(NULL)

Read the reasoning

The reproduction steps are clear and would demonstrate the behavior.

report:0

Deterministic checks that failed

  • file no file named include/tool_binmode.h has ever existed in curl
Read the original report (excerpt)

Full report on HackerOne ↗

Summary ------- Calling the `CURLX_SET_BINMODE(stream)` macro with `stream == NULL` leads to an unguarded call to `fileno(NULL)` in `tool_binmode.h`, which is undefined behavior and may crash the process. This is a robustness/UB issue and should be corrected by guarding against NULL streams before calling `fileno()`. Reproducer --------- A minimal test program is included below to demonstrate the issue. When built against the current header, running the program results in a crash (SIGSEGV) or other undefined behavior on many platforms. Impact ------ Non-security robustness defect: an accidental `NULL` stream passed to the macro can crash the process. This can surface during CLI tool execution or in tests and is easy to trigger accidentally. Fix --- Add a simple NULL-check wrapper (inline function) that returns early when `stream == NULL`, then call `_setmode`/`setmode` inside the wrapper. I included a suggested patch below and a unit test to prevent regressions. Notes ----- This is non-security; public PR is appropriate. I recommend adding the unit test to CI (and an ASAN job) so regressions are caught. (safe, reproducible) Save as repro_binmode_null.c at the repository root (adjust include path if needed): /* repro_binmode_null.c * * Minimal PoC demonstrating that calling CURLX_SET_BINMODE(NULL) * results in an unguarded fileno(NULL) invocation (undefined behavior). * * Build: * gcc -Wall -Wextra -g -I./include repro_binmode_null.c -o repro_binmode_null * * If you want a clearer diagnostic, build+run under ASAN: * gcc -fsanitize=address,undefined -g -I./include repro_binmode_null.c -o repro_binmode_null_asan * * Run: * ./repro_binmode_null * ./repro_binmode_null_asan * * Note: This program intentionally triggers the problematic call for repro purposes. */ #include <stdio.h> /* Adjust the path below if your include tree is located elsewhere */ #include "tool_binmode.h" int main(void) { /* Intentionally pass NULL to reproduce the issue. The current macro expands to fileno(NULL), which is UB. */ CURLX_SET_BINMODE(NULL); /* If the program continues without crashing, print a confirmation */ printf("CURLX_SET_BINMODE(NULL) returned — either implementation avoided fileno(NULL) or UB did not manifest.\n"); return 0; } Build & run instructions :- From the repo root (assuming include/tool_binmode.h ex …

Source code

lib/curlx/binmode.hlines 31–31 · definition of CURLX_SET_BINMODE
31# define CURLX_SET_BINMODE(stream) (void)_setmode(fileno(stream), O_BINARY)
C1: Macro definition: #define CURLX_SET_BINMODE(stream) (void)_setmode(fileno(stream), O_BINARY) — no NULL check before calling fileno(stream)
C2: The macro is actually defined in lib/curlx/binmode.h, not tool_binmode.h
C3: The macro takes a 'stream' parameter; passing NULL triggers the unguarded fileno(NULL) call
C4: fileno(NULL) is undefined behavior per POSIX and can crash on many platforms
src/curlinfo.clines 241–253 · definition of main
241int main(int argc, char **argv)
242{
243 size_t i;
244
245 (void)argc;
246 (void)argv;
247
248 for(i = 0; i < CURL_ARRAYSIZE(disabled); i++)
249 /* !checksrc! disable BANNEDFUNC 1 */
250 printf("%s\n", disabled[i]);
251
252 return 0;
253}
src/curlinfo.c@curl-8_16_0lines 243–254 · definition of main as in release curl-8_16_0; differs from master; commits that changed it since: db98daab05 src: stop overriding system printf symbols | 92f215fea1 build: address some `-Weverything` warnings, update picky warnings
Show 12 lines (not cited by the judge)
243int main(int argc, char **argv)
244{
245 int i;
246
247 (void)argc;
248 (void)argv;
249
250 for(i = 0; disabled[i]; i++)
251 printf("%s\n", disabled[i]);
252
253 return 0;
254}