{"record":{"id":"2f71bf8d0f9cef97","repo":"windmill-labs/windmill","slug":"fwrite-is-not-supported-2f71bf","errorCode":null,"errorMessage":"fwrite is not supported","messagePattern":"fwrite is not supported","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/parsers/windmill-parser-ruby/src/wasm_libc.rs","lineNumber":266,"sourceCode":"\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: ...\n) -> c_int {\n    panic!(\"vsnprintf is not supported\");\n}\n\n#[no_mangle]\npub extern \"C\" fn clock_gettime(ptr: usize, new_size: usize) {\n    panic!(\"clock_gettime is not supported\");\n}\n\n// int snprintf( char* restrict buffer, size_t bufsz, const char* restrict format, ... );","sourceCodeStart":248,"sourceCodeEnd":284,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/backend/parsers/windmill-parser-ruby/src/wasm_libc.rs#L248-L284","documentation":"The WASM Ruby parser stubs libc `fwrite` with an unconditional panic because writing to C stdio streams is impossible in the sandbox. Any Ruby VM or parsed code path that writes to a FILE* stream aborts with this message. It is a deliberate guard against unsupported libc surface.","triggerScenarios":"Calling the exported `fwrite` symbol, or Ruby code whose execution path performs buffered stream writes (puts/print to a stdio FILE*, gem internals using fwrite).","commonSituations":"Ruby script prints to a file handle or a gem writes via stdio during parsing; no real stream exists in wasm so the stub fires.","solutions":["Remove stream writes from the Ruby code under parse; return values instead of writing them out","Use in-memory constructs (strings, arrays) rather than IO objects","Implement a WASI-backed fwrite shim if output streaming is a real requirement"],"exampleFix":"// before\nFile.open('out.txt', 'w') { |f| f.write(data) }\n// after\nreturn data # let the host handle persistence","handlingStrategy":"validation","validationCode":"fn writes_to_streams(ruby_src: &str) -> bool {\n    [\"File.open\", \"IO.write\", \"f.write\", \".puts\", \".print\"]\n        .iter().any(|p| ruby_src.contains(p))\n}","typeGuard":null,"tryCatchPattern":"match std::panic::catch_unwind(|| parse_ruby(source)) {\n    Ok(res) => res,\n    Err(e) => { log::warn!(\"ruby parser: stream write attempted in sandbox\"); Err(format_parser_error(e)) }\n}","preventionTips":["Have scripts return data instead of writing it to files/streams","Reject scripts using IO write APIs during submission","Keep parser-facing gems pure-Ruby where possible"],"tags":["wasm","ruby","libc","unsupported-operation"],"backgroundTag":"wasm-unsupported-libc-call","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"}