blob: 1eb5f795e43f40dee6e73bc89fe6bc8e4bacdf6c [file] [log] [blame]
Hasnain Lakhaniaa183322025-08-25 13:54:33 -07001const thrift = require("../../lib/thrift");
2const FuzzTest = require("./gen-nodejs/FuzzTestNoUuid_types");
3// const { FuzzedDataProvider } = require("@jazzer.js/core");
4
5/**
6 * Creates a parser fuzzer function for a specific protocol
7 * @param {Function} protocolFactory - The Thrift protocol factory function
8 * @param {boolean} [readMessageBegin=false] - Whether to call readMessageBegin before reading the test instance
9 * This is needed for protocols that do not support parsing just a struct, such as TJSONProtocol.
10 * @returns {Function} A fuzzer function that can be used with Jazzer.js
11 */
12function createParserFuzzer(protocolFactory, readMessageBegin = false) {
13 return function fuzz(data) {
14 if (data.length < 2) {
15 return;
16 }
17
18 try {
19 // Set up transport with input data
20 const transport = new thrift.TFramedTransport(data);
21 const protocol = protocolFactory(transport);
22 const testInstance = new FuzzTest.FuzzTest();
23 if (readMessageBegin) {
24 protocol.readMessageBegin();
25 }
26 testInstance[Symbol.for("read")](protocol);
27 } catch (e) {
28 if (
29 !(
30 e.name === "InputBufferUnderrunError" ||
31 e.name === "TProtocolException"
32 )
33 ) {
34 // TODO: Are other exceptions expected?
35 // console.log(e);
36 }
37 }
38 };
39}
40
41/**
42 * Creates a roundtrip fuzzer function for a specific protocol
43 * @param {Function} protocolFactory - The Thrift protocol factory function
44 * @param {boolean} [readMessageBegin=false] - Whether to call readMessageBegin before reading the test instance
45 * This is needed for protocols that do not support parsing just a struct, such as TJSONProtocol.
46 * @returns {Function} A fuzzer function that can be used with Jazzer.js
47 */
48function createRoundtripFuzzer(protocolFactory, readMessageBegin = false) {
49 return function fuzz(data) {
50 if (data.length < 2) {
51 return;
52 }
53
54 try {
55 // First deserialize using framed transport for input
56 const transport1 = new thrift.TFramedTransport(data);
57 const protocol1 = protocolFactory(transport1);
58 const testInstance = new FuzzTest.FuzzTest();
59 if (readMessageBegin) {
60 protocol1.readMessageBegin();
61 }
62 testInstance[Symbol.for("read")](protocol1);
63
64 // Then serialize using buffered transport with callback
65 let serializedData;
66 const transport2 = new thrift.TBufferedTransport(null, function (buf) {
67 serializedData = buf;
68 });
69 const protocol2 = protocolFactory(transport2);
70 testInstance[Symbol.for("write")](protocol2);
71 protocol2.flush();
72
73 if (!serializedData) {
74 throw new Error("Serialization failed - no data produced");
75 }
76
77 // Finally deserialize again and compare using framed transport
78 const transport3 = new thrift.TFramedTransport(serializedData);
79 const protocol3 = protocolFactory(transport3);
80 const deserialized = new FuzzTest.FuzzTest();
81 if (readMessageBegin) {
82 protocol3.readMessageBegin();
83 }
84 deserialized[Symbol.for("read")](protocol3);
85
86 // Compare the objects
87 if (!testInstance.equals(deserialized)) {
88 throw new Error("Roundtrip comparison failed");
89 }
90 } catch (e) {
91 if (
92 !(
93 e.name === "InputBufferUnderrunError" ||
94 e.name === "TProtocolException"
95 )
96 ) {
97 // TODO: Are other exceptions expected?
98 // console.log(e);
99 }
100 }
101 };
102}
103
104module.exports = {
105 createParserFuzzer,
106 createRoundtripFuzzer,
107};