{"record":{"id":"234c34e1f2d31e30","repo":"windmill-labs/windmill","slug":"fclose-is-not-supported-234c34","errorCode":null,"errorMessage":"fclose is not supported","messagePattern":"fclose is not supported","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/parsers/windmill-parser-r/src/wasm_libc.rs","lineNumber":256,"sourceCode":"\n#[no_mangle]\npub unsafe extern \"C\" fn fputs(_s: *const c_void, _file: *mut c_void) -> c_int {\n    panic!(\"fputs is not supported\");\n}\n\n#[no_mangle]\npub unsafe extern \"C\" fn fputc(_c: c_int, _file: *mut c_void) -> c_int {\n    panic!(\"fputc is not supported\");\n}\n\n#[no_mangle]\npub unsafe extern \"C\" fn fdopen(_fd: c_int, _mode: *const c_void) -> *mut c_void {\n    panic!(\"fdopen is not supported\");\n}\n\n#[no_mangle]\npub unsafe extern \"C\" fn fclose(_file: *mut c_void) -> c_int {\n    panic!(\"fclose is not supported\");\n}\n\n#[no_mangle]\npub unsafe extern \"C\" fn fwrite(\n    _ptr: *const c_void,\n    _size: usize,\n    _nmemb: usize,\n    _stream: *mut c_void,\n) -> usize {\n    panic!(\"fwrite is not supported\");\n}\n\n#[no_mangle]\npub unsafe extern \"C\" fn vsnprintf(\n    _buf: *mut c_char,\n    _size: usize,\n    _format: *const c_char,\n    _args: ...","sourceCodeStart":238,"sourceCodeEnd":274,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/backend/parsers/windmill-parser-r/src/wasm_libc.rs#L238-L274","documentation":"`fclose` (close a FILE* stream) is a panicking stub in the R parser's WASM libc shim layer. Since no stream can be opened in the first place (fopen/fdopen are unsupported), reaching fclose means code is unconditionally running a stdio lifecycle the sandbox never implemented.","triggerScenarios":"Calling the exported `fclose` shim at backend/parsers/windmill-parser-r/src/wasm_libc.rs:256, typically cleanup code in compiled C/R runtime that closes streams on exit or error paths.","commonSituations":"Library teardown code always calls fclose; R script uses file connections that compile to stdio calls; a dependency's destructor flushes and closes streams.","solutions":["Remove/guard the stream-cleanup code path since no real streams exist in the WASM sandbox","Implement fclose as a no-op returning 0 if linked code unconditionally calls it","Rewrite the R/C code to avoid FILE* connections, using supported input/output mechanisms","Track as an unsupported-symbol gap and emulate a minimal stream lifecycle if needed"],"exampleFix":"// before (stub)\n#[no_mangle]\npub unsafe extern \"C\" fn fclose(_file: *mut c_void) -> c_int {\n    panic!(\"fclose is not supported\");\n}\n// after (safe no-op for unreachable streams)\n#[no_mangle]\npub unsafe extern \"C\" fn fclose(_file: *mut c_void) -> c_int {\n    0 // no real streams exist in WASM; succeed harmlessly\n}","handlingStrategy":"try-catch","validationCode":"// If no stream can be opened, fclose can never be legitimate: flag stream lifecycle code\nif (/\\b(fopen|fdopen|fclose)\\s*\\(/.test(source)) {\n  console.warn(\"source uses FILE* lifecycle APIs unsupported by the R parser WASM\");\n}","typeGuard":"// Rust: FILE* handles from this sandbox are always null/invalid\nfn stream_valid(file: *mut c_void) -> bool { !file.is_null() } // always false here; any close path is dead code","tryCatchPattern":"let res = std::panic::catch_unwind(AssertUnwindSafe(|| run_wasm_r(source)));\nmatch res {\n    Ok(v) => v,\n    Err(p) if panic_msg(&p).contains(\"fclose is not supported\") => {\n        // strip or stub the stream-cleanup path in the source and retry once\n        retry_without_stream_teardown(source)\n    }\n    Err(p) => std::panic::resume_unwind(p),\n}","preventionTips":["Remove stream open/close lifecycle code from payloads intended for the WASM parser","Treat any FILE* value in this sandbox as invalid — never call closers on it","If linked C code always calls fclose, provide a no-op shim rather than a panic","Cover teardown paths in tests; they often run only on error exits"],"tags":["wasm","libc","rust","file-io"],"backgroundTag":"wasm-libc-function-not-supported","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}