I am a researcher in software testing from the University of Stuttgart, Germany. We are testing grammar-based fuzzers and have chosen JerryScript as one of our fuzz targets for JavaScript. During our experiments we found 4 issues with JerryScript that I'd like to share with you. 

Please excuse if some of the examples may look weird. This is typically the case when generating random test inputs. I verified crashes/issues by cross-checking the behavior with the JavaScript engines that Firefox or Chrome use. Thus, I am sometimes not entirely sure whether JerryScript or Firefox or Chrome misbehave.

All issues can be split into separate ones if required.

###### JerryScript revision
`3.0.0 - 1a2c04763aba49f52b1537acd3730098c873511c`

###### Build platform
`Rocky Linux release 9.1 (Blue Onyx), 5.14.0-162.18.1.el9_1.x86_64`

###### Build steps
```sh
python3 tools/build.py
```

###### Build logs
```
-- The C compiler identification is GNU 11.3.1
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- CMAKE_BUILD_TYPE               MinSizeRel
-- CMAKE_C_COMPILER_ID            GNU
-- CMAKE_SYSTEM_NAME              Linux
-- CMAKE_SYSTEM_PROCESSOR         x86_64
-- BUILD_SHARED_LIBS              OFF
-- ENABLE_AMALGAM                 OFF
-- ENABLE_LTO                     ON
-- ENABLE_STRIP                   ON
-- ENABLE_COMPILE_COMMANDS        ON
-- JERRY_VERSION                  3.0.0
-- JERRY_CMDLINE                  ON
-- JERRY_CMDLINE_TEST             OFF
-- JERRY_CMDLINE_SNAPSHOT         OFF
-- JERRY_LIBFUZZER                OFF (FORCED BY COMPILER)
-- JERRY_PORT                     ON (FORCED BY CMDLINE OR LIBFUZZER OR TESTS)
-- JERRY_EXT                      ON (FORCED BY CMDLINE OR TESTS)
-- JERRY_MATH                     OFF
-- UNITTESTS                      OFF
-- DOCTESTS                       OFF
-- JERRY_CPOINTER_32_BIT          OFF
-- JERRY_DEBUGGER                 OFF
-- JERRY_ERROR_MESSAGES           OFF
-- JERRY_EXTERNAL_CONTEXT         OFF
-- JERRY_PARSER                   ON
-- JERRY_FUNCTION_TO_STRING       OFF
-- JERRY_LINE_INFO                OFF
-- JERRY_LOGGING                  OFF
-- JERRY_MEM_STATS                OFF
-- JERRY_MEM_GC_BEFORE_EACH_ALLOC OFF
-- JERRY_PARSER_DUMP_BYTE_CODE    OFF
-- JERRY_PROFILE                  es.next
-- JERRY_PROMISE_CALLBACK         OFF
-- JERRY_REGEXP_STRICT_MODE       OFF
-- JERRY_REGEXP_DUMP_BYTE_CODE    OFF
-- JERRY_SNAPSHOT_EXEC            OFF
-- JERRY_SNAPSHOT_SAVE            OFF
-- JERRY_SYSTEM_ALLOCATOR         OFF
-- JERRY_VALGRIND                 OFF
-- JERRY_VM_HALT                  OFF
-- JERRY_VM_THROW                 OFF
-- JERRY_GLOBAL_HEAP_SIZE         (512)
-- JERRY_GC_LIMIT                 (0)
-- JERRY_STACK_LIMIT              (0)
-- JERRY_GC_MARK_LIMIT            (8)
-- Looking for sin in m
-- Looking for sin in m - found
-- FEATURE_INIT_FINI              OFF
-- Performing Test HAVE_TM_GMTOFF
-- Performing Test HAVE_TM_GMTOFF - Success
-- ENABLE_LINK_MAP                OFF
-- JERRY_TEST_STACK_MEASURE       OFF
```

---
### Issue 1 - Arrays with self-references result in a core dump when printed

###### Test case
`test1.js`
```JavaScript
a = []
a[0] = 5  /* works */
a[1] = a  /* fails! core dump */
```

###### Execution
`cat test1.js | ./build/bin/jerry`

###### Output
```
jerry> 
jerry> 5
jerry> Aborted (core dumped)
```

###### Expected behavior
Should print the array as something like `[5, a]` without resulting in a core dump. I suppose that it is an issue with the (console) print function not handling already resolved references correctly? When executing without piping it to the binary it seems to work. Also executing `a = []; a[0] = 5; a[1] = a; a[2] = 4; print(a[1][2]);` works and prints `4`. I guess that once a reference in the print statement is resolved for an object, the print should not recurse again?

---
### Issue 2 - Editing the prototype of `this` by assigning a Proxy object leads to core dumps in some cases, while in other cases, it doesn't result in a core dump but should print an error

###### Test case
`test2.js`
```JavaScript
this.__proto__ = new Proxy(Number, this.__proto__);                     /* works, but shouldn't? */
Number.__proto__ = this.__proto__ = new Proxy(Number, this.__proto__);  /* core dump */
```

###### Execution
`cat test2.js | ./build/bin/jerry`

###### Output
```
jerry> function () { [native code] }
jerry> Aborted (core dumped)
```

###### Expected behavior
I assume that both statements should result in similar messages like for example in Firefox `Uncaught TypeError: can't set prototype of this object` or Chrome `Uncaught TypeError: Immutable prototype object '#<Window>' cannot have their prototype set`. However, I am not aware whether it has to do something with the fact that `this` is something different in the browsers but not in JerryScript.

---
### Issue 3 - Editing the prototype of objects like `Number` or `Array` by assigning a Proxy leads to a segmentation fault (core dump)

###### Test case
`test3.js`
```JavaScript
Number.__proto__ = new Proxy(Number, {})
```

###### Execution
`cat test3.js | ./build/bin/jerry`

###### Output
```
Segmentation fault (core dumped)
```

###### Expected behavior
Should print something like `Proxy { <target>: Number(), <handler>: {} }`. I suppose this is similar to issue 1 with resolving recursive references?

---
### Issue 4 - Chained assignments cause in some cases core dumps while working as expected when executed on their own

###### Test case
`test4.js`
```JavaScript
{}.__proto__[20] = new Array(1000.00)          /* works, syntax error */
myvar = {}.__proto__[20]                       /* works, undefined */
myvar = {}.__proto__[20] = new Array(1000.00)  /* core dump */
```

###### Execution
`cat test4.js | ./build/bin/jerry`

###### Output
```
jerry> Unhandled exception: SyntaxError
jerry> undefined
jerry> Aborted (core dumped)
```

###### Expected behavior
This should result in printing an empty array with 1000 slots (similar to `new Array(1000.00)` which works just fine). Although this also only happens when the console print is executed, I think `myvar` actually does not get the correct value assigned, i.e. `new Array(1000.00)`. However, I am not sure whether ignoring a sub-expression that results in an syntax error should be treated as "non-existent" or whether the whole statement should be discarded in a syntax error.
Four issues found through grammar-based fuzzing
This is a GitHub Issue
repo:jerryscript
owner:jerryscript-project
Title : Four issues found through grammar-based fuzzing
Issue date:

--- start body ---
I am a researcher in software testing from the University of Stuttgart, Germany. We are testing grammar-based fuzzers and have chosen JerryScript as one of our fuzz targets for JavaScript. During our experiments we found 4 issues with JerryScript that I'd like to share with you. 

Please excuse if some of the examples may look weird. This is typically the case when generating random test inputs. I verified crashes/issues by cross-checking the behavior with the JavaScript engines that Firefox or Chrome use. Thus, I am sometimes not entirely sure whether JerryScript or Firefox or Chrome misbehave.

All issues can be split into separate ones if required.

###### JerryScript revision
`3.0.0 - 1a2c04763aba49f52b1537acd3730098c873511c`

###### Build platform
`Rocky Linux release 9.1 (Blue Onyx), 5.14.0-162.18.1.el9_1.x86_64`

###### Build steps
```sh
python3 tools/build.py
```

###### Build logs
```
-- The C compiler identification is GNU 11.3.1
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- CMAKE_BUILD_TYPE               MinSizeRel
-- CMAKE_C_COMPILER_ID            GNU
-- CMAKE_SYSTEM_NAME              Linux
-- CMAKE_SYSTEM_PROCESSOR         x86_64
-- BUILD_SHARED_LIBS              OFF
-- ENABLE_AMALGAM                 OFF
-- ENABLE_LTO                     ON
-- ENABLE_STRIP                   ON
-- ENABLE_COMPILE_COMMANDS        ON
-- JERRY_VERSION                  3.0.0
-- JERRY_CMDLINE                  ON
-- JERRY_CMDLINE_TEST             OFF
-- JERRY_CMDLINE_SNAPSHOT         OFF
-- JERRY_LIBFUZZER                OFF (FORCED BY COMPILER)
-- JERRY_PORT                     ON (FORCED BY CMDLINE OR LIBFUZZER OR TESTS)
-- JERRY_EXT                      ON (FORCED BY CMDLINE OR TESTS)
-- JERRY_MATH                     OFF
-- UNITTESTS                      OFF
-- DOCTESTS                       OFF
-- JERRY_CPOINTER_32_BIT          OFF
-- JERRY_DEBUGGER                 OFF
-- JERRY_ERROR_MESSAGES           OFF
-- JERRY_EXTERNAL_CONTEXT         OFF
-- JERRY_PARSER                   ON
-- JERRY_FUNCTION_TO_STRING       OFF
-- JERRY_LINE_INFO                OFF
-- JERRY_LOGGING                  OFF
-- JERRY_MEM_STATS                OFF
-- JERRY_MEM_GC_BEFORE_EACH_ALLOC OFF
-- JERRY_PARSER_DUMP_BYTE_CODE    OFF
-- JERRY_PROFILE                  es.next
-- JERRY_PROMISE_CALLBACK         OFF
-- JERRY_REGEXP_STRICT_MODE       OFF
-- JERRY_REGEXP_DUMP_BYTE_CODE    OFF
-- JERRY_SNAPSHOT_EXEC            OFF
-- JERRY_SNAPSHOT_SAVE            OFF
-- JERRY_SYSTEM_ALLOCATOR         OFF
-- JERRY_VALGRIND                 OFF
-- JERRY_VM_HALT                  OFF
-- JERRY_VM_THROW                 OFF
-- JERRY_GLOBAL_HEAP_SIZE         (512)
-- JERRY_GC_LIMIT                 (0)
-- JERRY_STACK_LIMIT              (0)
-- JERRY_GC_MARK_LIMIT            (8)
-- Looking for sin in m
-- Looking for sin in m - found
-- FEATURE_INIT_FINI              OFF
-- Performing Test HAVE_TM_GMTOFF
-- Performing Test HAVE_TM_GMTOFF - Success
-- ENABLE_LINK_MAP                OFF
-- JERRY_TEST_STACK_MEASURE       OFF
```

---
### Issue 1 - Arrays with self-references result in a core dump when printed

###### Test case
`test1.js`
```JavaScript
a = []
a[0] = 5  /* works */
a[1] = a  /* fails! core dump */
```

###### Execution
`cat test1.js | ./build/bin/jerry`

###### Output
```
jerry> 
jerry> 5
jerry> Aborted (core dumped)
```

###### Expected behavior
Should print the array as something like `[5, a]` without resulting in a core dump. I suppose that it is an issue with the (console) print function not handling already resolved references correctly? When executing without piping it to the binary it seems to work. Also executing `a = []; a[0] = 5; a[1] = a; a[2] = 4; print(a[1][2]);` works and prints `4`. I guess that once a reference in the print statement is resolved for an object, the print should not recurse again?

---
### Issue 2 - Editing the prototype of `this` by assigning a Proxy object leads to core dumps in some cases, while in other cases, it doesn't result in a core dump but should print an error

###### Test case
`test2.js`
```JavaScript
this.__proto__ = new Proxy(Number, this.__proto__);                     /* works, but shouldn't? */
Number.__proto__ = this.__proto__ = new Proxy(Number, this.__proto__);  /* core dump */
```

###### Execution
`cat test2.js | ./build/bin/jerry`

###### Output
```
jerry> function () { [native code] }
jerry> Aborted (core dumped)
```

###### Expected behavior
I assume that both statements should result in similar messages like for example in Firefox `Uncaught TypeError: can't set prototype of this object` or Chrome `Uncaught TypeError: Immutable prototype object '#<Window>' cannot have their prototype set`. However, I am not aware whether it has to do something with the fact that `this` is something different in the browsers but not in JerryScript.

---
### Issue 3 - Editing the prototype of objects like `Number` or `Array` by assigning a Proxy leads to a segmentation fault (core dump)

###### Test case
`test3.js`
```JavaScript
Number.__proto__ = new Proxy(Number, {})
```

###### Execution
`cat test3.js | ./build/bin/jerry`

###### Output
```
Segmentation fault (core dumped)
```

###### Expected behavior
Should print something like `Proxy { <target>: Number(), <handler>: {} }`. I suppose this is similar to issue 1 with resolving recursive references?

---
### Issue 4 - Chained assignments cause in some cases core dumps while working as expected when executed on their own

###### Test case
`test4.js`
```JavaScript
{}.__proto__[20] = new Array(1000.00)          /* works, syntax error */
myvar = {}.__proto__[20]                       /* works, undefined */
myvar = {}.__proto__[20] = new Array(1000.00)  /* core dump */
```

###### Execution
`cat test4.js | ./build/bin/jerry`

###### Output
```
jerry> Unhandled exception: SyntaxError
jerry> undefined
jerry> Aborted (core dumped)
```

###### Expected behavior
This should result in printing an empty array with 1000 slots (similar to `new Array(1000.00)` which works just fine). Although this also only happens when the console print is executed, I think `myvar` actually does not get the correct value assigned, i.e. `new Array(1000.00)`. However, I am not sure whether ignoring a sub-expression that results in an syntax error should be treated as "non-existent" or whether the whole statement should be discarded in a syntax error.
--- end body ---

The issues identified in JerryScript through grammar-based fuzzing indicate potential vulnerabilities that could lead to Denial of Service (DoS) conditions. Specifically, the core dumps resulting from self-references in arrays, improper handling of prototype assignments with Proxy objects, and chained assignments suggest that the engine does not adequately handle certain edge cases, which could be exploited to crash the interpreter.