Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support crash triaging for jsfuzz #122

Closed
SweetVishnya opened this issue Aug 22, 2023 · 11 comments · Fixed by #176
Closed

Support crash triaging for jsfuzz #122

SweetVishnya opened this issue Aug 22, 2023 · 11 comments · Fixed by #176
Assignees
Labels
enhancement New feature or request

Comments

@SweetVishnya
Copy link
Collaborator

It would be nice to support Java Script fuzzer called jsfuzz in casr-libfuzzer similar to jazzer.

@SweetVishnya SweetVishnya added the enhancement New feature or request label Sep 7, 2023
@SweetVishnya SweetVishnya added the help wanted Extra attention is needed label Sep 17, 2023
@0xricksanchez
Copy link

@SweetVishnya Maybe since you're already supporting Jazzer, how about adding support for Jazzer.js as well. It's currently also still based on libfuzzer and I could imagine adding support should be doable with the foundation you already have.

@PaDarochek
Copy link
Member

PaDarochek commented Oct 4, 2023

When coding support for JS stacktrace parsing, I faced some interesting situation. If we want to compare two stacktrace entries, according to the logic of CASR we should consider the filenames (with locations in files), module names and addresses equality. In JS stacktraces module names and addresses are not presented, so the comparison is made based on filenames (with locations in files) equality.

But if at least one of the filenames is empty, then the entries are considered equal. It is a strange situation but as I could search it is possible that some stacktrace entries can have empty filenames, like this:

Uncaught Error  
    at query (:10:11)  
    at database (:6:5)  
    at controller (:2:5)  

The logic of CASR now doesn't suppose to take function names into account.
So any ideas about how should we compare such entries? Or am I wrong and this is an impossible situation?
@SweetVishnya @0xricksanchez

@anfedotoff
Copy link
Collaborator

at query (:10:11)
at database (:6:5)
at controller (:2:5)

Maybe it is an offset from the beginning of the function? Is it possible to check? If it is so, we don't have function name. In this case function is a file path in our terminology.

@PaDarochek
Copy link
Member

PaDarochek commented Oct 6, 2023

at query (:10:11)
at database (:6:5)
at controller (:2:5)

Maybe it is an offset from the beginning of the function? Is it possible to check? If it is so, we don't have function name. In this case function is a file path in our terminology.

In this example it is exactly an offset from the beginning of the file, not from the beginning of the function. These functions are located in the same file, one after another. It seems to me that this is not the situation you describe.

@SweetVishnya
Copy link
Collaborator Author

at query (:10:11)
at database (:6:5)
at controller (:2:5)

Maybe it is an offset from the beginning of the function? Is it possible to check? If it is so, we don't have function name. In this case function is a file path in our terminology.

In this example it is exactly an offset from the beginning of the file, not from the beginning of the function. These functions are located in the same file, one after another. It seems to me that this is not the situation you describe.

Maybe, there is a way of printing more meaningful stack traces: https://stackoverflow.com/a/635852

@PaDarochek
Copy link
Member

at query (:10:11)
at database (:6:5)
at controller (:2:5)

Maybe it is an offset from the beginning of the function? Is it possible to check? If it is so, we don't have function name. In this case function is a file path in our terminology.

In this example it is exactly an offset from the beginning of the file, not from the beginning of the function. These functions are located in the same file, one after another. It seems to me that this is not the situation you describe.

Maybe, there is a way of printing more meaningful stack traces: https://stackoverflow.com/a/635852

As I found out, both Jazzer-js and jsfuzz print stacktraces in V8 format. According to this format, the location in a stacktrace entry should contain some filename (except for native and unknown locations). Maybe we can assume that the filename should not be empty.

@anfedotoff
Copy link
Collaborator

at query (:10:11)
at database (:6:5)
at controller (:2:5)

Maybe it is an offset from the beginning of the function? Is it possible to check? If it is so, we don't have function name. In this case function is a file path in our terminology.

In this example it is exactly an offset from the beginning of the file, not from the beginning of the function. These functions are located in the same file, one after another. It seems to me that this is not the situation you describe.

Maybe, there is a way of printing more meaningful stack traces: https://stackoverflow.com/a/635852

As I found out, both Jazzer-js and jsfuzz print stacktraces in V8 format. According to this format, the location in a stacktrace entry should contain some filename (except for native and unknown locations). Maybe we can assume that the filename should not be empty.

Good news! I think we can relay on this and assume that filepath is not empty. Please, put some comment with this info in the code.

@0xricksanchez
Copy link

I don't know a whole lot about jsfuzz but as for Jazzer.js a typical stack trace looks similar to this:

==97930== Uncaught Exception: Jazzer.js: Error: Debug Failure. False expression: Containing file is missing import meta node flag.
    at checkImportMetaProperty (TypeScript/node_modules/typescript/lib/typescript.js:74543:13)
    at checkMetaProperty (TypeScript/node_modules/typescript/lib/typescript.js:74506:16)
    at checkExpressionWorker (TypeScript/node_modules/typescript/lib/typescript.js:77249:18)
    at checkExpression (TypeScript/node_modules/typescript/lib/typescript.js:77138:34)
    at maybeCheckExpression (TypeScript/node_modules/typescript/lib/typescript.js:76222:30)
    at BinaryExpressionStateMachine.onRight (TypeScript/node_modules/typescript/lib/typescript.js:76186:18)
    at Array.right (TypeScript/node_modules/typescript/lib/typescript.js:27825:36)
    at trampoline (TypeScript/node_modules/typescript/lib/typescript.js:27591:44)
    at checkBinaryExpression (TypeScript/node_modules/typescript/lib/typescript.js:76116:24)
    at checkExpressionWorker (TypeScript/node_modules/typescript/lib/typescript.js:77261:18)
    at checkExpression (TypeScript/node_modules/typescript/lib/typescript.js:77138:34)
    at checkExpressionStatement (TypeScript/node_modules/typescript/lib/typescript.js:79763:7)
    at checkSourceElementWorker (TypeScript/node_modules/typescript/lib/typescript.js:82707:18)
    at callback (TypeScript/node_modules/typescript/lib/typescript.js:82567:9)
    at forEach (ypeScript/node_modules/typescript/lib/typescript.js:55:24)
    at checkSourceFileWorker (TypeScript/node_modules/typescript/lib/typescript.js:82940:9)
    at checkSourceFile (TypeScript/node_modules/typescript/lib/typescript.js:82907:7)
    at callback (TypeScript/node_modules/typescript/lib/typescript.js:83001:7)
    at forEach (TypeScript/node_modules/typescript/lib/typescript.js:55:24)
    at getDiagnosticsWorker (TypeScript/node_modules/typescript/lib/typescript.js:83020:7)
    at getDiagnostics2 (TypeScript/node_modules/typescript/lib/typescript.js:82986:16)
    at Object.getEmitResolver (TypeScript/node_modules/typescript/lib/typescript.js:46472:7)
    at emitWorker (TypeScript/node_modules/typescript/lib/typescript.js:119325:45)
    at func (TypeScript/node_modules/typescript/lib/typescript.js:119312:53)
    at runWithCancellationToken (TypeScript/node_modules/typescript/lib/typescript.js:119401:16)
    at Object.emit (TypeScript/node_modules/typescript/lib/typescript.js:119312:22)
    at Object.transpileModule (TypeScript/node_modules/typescript/lib/typescript.js:134790:13)
    at module.exports.fuzz (TypeScript/fuzz_transpile_module.js:30:8)

As we're building custom bug detectors into Jazzer.js the format can slightly differ for the first line where we have the Uncaught Exception. E.g if you run the path-traversal detection example in the Jazzer.js repo you get something like this:

#18206  REDUCE cov: 273 ft: 1069 corp: 153/29Kb lim: 470 exec/s: 0 rss: 205Mb L: 50/470 MS: 3 CopyPart-ShuffleBytes-EraseBytes-
#18397  NEW    cov: 273 ft: 1070 corp: 154/30Kb lim: 470 exec/s: 0 rss: 205Mb L: 470/470 MS: 1 ChangeBit-
#18715  REDUCE cov: 273 ft: 1070 corp: 154/30Kb lim: 470 exec/s: 0 rss: 205Mb L: 56/470 MS: 3 CopyPart-InsertByte-EraseBytes-
#19060  REDUCE cov: 273 ft: 1070 corp: 154/30Kb lim: 470 exec/s: 0 rss: 206Mb L: 126/470 MS: 5 ChangeBit-ChangeByte-ChangeBit-ChangeBinInt-EraseBytes-
==96950== Path Traversal in normalize(): called with 'jazzer.js/examples/bug-detectors/path-traversal//UT   /UT�ldux
                                                                                                                                                �dPK
�k�V
�A?test/test/UT�ldux
                    �dPK
�k�Vest/exampleU../../jaz_zerx
                              �dPK
�k�V;@�Atest/UT�ldux
                    /'
    at Object.join (node:path:1182:18)
    at jazzer.js/examples/bug-detectors/path-traversal/fuzz.js:37:11

All custom bug detectors are WIP and are still not finalized. If you guys have input on this to make automation easier, dropping an issue in the repo sounds like a good idea!

@PaDarochek
Copy link
Member

@0xricksanchez Thanks for the detailed explanation! As for strings related to the stacktrace entries, I think we can rely on V8 docs as such strings in Jazzer-js totally correspond to this format.
But what about the first string - can you please tell us if there is a common pattern that we can use to recognize the string as the first string before the stacktrace begins?

@0xricksanchez
Copy link

0xricksanchez commented Oct 11, 2023

@0xricksanchez Thanks for the detailed explanation! As for strings related to the stacktrace entries, I think we can rely on V8 docs as such strings in Jazzer-js totally correspond to this format. But what about the first string - can you please tell us if there is a common pattern that we can use to recognize the string as the first string before the stacktrace begins?

The current formatting is defined here.

The basic shape roughly corresponds to:

==<PID>== Uncaught Exception: <ERR>
<TRACE>

@hkctkuy hkctkuy linked a pull request Nov 9, 2023 that will close this issue
@SweetVishnya SweetVishnya removed the help wanted Extra attention is needed label Nov 25, 2023
@PaDarochek
Copy link
Member

@0xricksanchez Support for crash triaging via casr-libfuzzer for both Jazzer.js and jsfuzz has just been added to CASR!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants