| const thrift = require("../../lib/thrift"); |
| const FuzzTest = require("./gen-nodejs/FuzzTestNoUuid_types"); |
| // const { FuzzedDataProvider } = require("@jazzer.js/core"); |
| |
| /** |
| * Creates a parser fuzzer function for a specific protocol |
| * @param {Function} protocolFactory - The Thrift protocol factory function |
| * @param {boolean} [readMessageBegin=false] - Whether to call readMessageBegin before reading the test instance |
| * This is needed for protocols that do not support parsing just a struct, such as TJSONProtocol. |
| * @returns {Function} A fuzzer function that can be used with Jazzer.js |
| */ |
| function createParserFuzzer(protocolFactory, readMessageBegin = false) { |
| return function fuzz(data) { |
| if (data.length < 2) { |
| return; |
| } |
| |
| try { |
| // Set up transport with input data |
| const transport = new thrift.TFramedTransport(data); |
| const protocol = protocolFactory(transport); |
| const testInstance = new FuzzTest.FuzzTest(); |
| if (readMessageBegin) { |
| protocol.readMessageBegin(); |
| } |
| testInstance[Symbol.for("read")](protocol); |
| } catch (e) { |
| if ( |
| !( |
| e.name === "InputBufferUnderrunError" || |
| e.name === "TProtocolException" |
| ) |
| ) { |
| // TODO: Are other exceptions expected? |
| // console.log(e); |
| } |
| } |
| }; |
| } |
| |
| /** |
| * Creates a roundtrip fuzzer function for a specific protocol |
| * @param {Function} protocolFactory - The Thrift protocol factory function |
| * @param {boolean} [readMessageBegin=false] - Whether to call readMessageBegin before reading the test instance |
| * This is needed for protocols that do not support parsing just a struct, such as TJSONProtocol. |
| * @returns {Function} A fuzzer function that can be used with Jazzer.js |
| */ |
| function createRoundtripFuzzer(protocolFactory, readMessageBegin = false) { |
| return function fuzz(data) { |
| if (data.length < 2) { |
| return; |
| } |
| |
| try { |
| // First deserialize using framed transport for input |
| const transport1 = new thrift.TFramedTransport(data); |
| const protocol1 = protocolFactory(transport1); |
| const testInstance = new FuzzTest.FuzzTest(); |
| if (readMessageBegin) { |
| protocol1.readMessageBegin(); |
| } |
| testInstance[Symbol.for("read")](protocol1); |
| |
| // Then serialize using buffered transport with callback |
| let serializedData; |
| const transport2 = new thrift.TBufferedTransport(null, function (buf) { |
| serializedData = buf; |
| }); |
| const protocol2 = protocolFactory(transport2); |
| testInstance[Symbol.for("write")](protocol2); |
| protocol2.flush(); |
| |
| if (!serializedData) { |
| throw new Error("Serialization failed - no data produced"); |
| } |
| |
| // Finally deserialize again and compare using framed transport |
| const transport3 = new thrift.TFramedTransport(serializedData); |
| const protocol3 = protocolFactory(transport3); |
| const deserialized = new FuzzTest.FuzzTest(); |
| if (readMessageBegin) { |
| protocol3.readMessageBegin(); |
| } |
| deserialized[Symbol.for("read")](protocol3); |
| |
| // Compare the objects |
| if (!testInstance.equals(deserialized)) { |
| throw new Error("Roundtrip comparison failed"); |
| } |
| } catch (e) { |
| if ( |
| !( |
| e.name === "InputBufferUnderrunError" || |
| e.name === "TProtocolException" |
| ) |
| ) { |
| // TODO: Are other exceptions expected? |
| // console.log(e); |
| } |
| } |
| }; |
| } |
| |
| module.exports = { |
| createParserFuzzer, |
| createRoundtripFuzzer, |
| }; |