Skip to content

Infinite recursion resutls in stack overflow #5285

@davidlie

Description

@davidlie

Setting a Proxy as its own prototype creates a cycle in the [[GetPrototypeOf]] chain. Any property lookup on the object enters ecma_proxy_object_getecma_op_object_get_with_receiverecma_proxy_object_get without bound. JerryScript has no prototype-cycle guard and no recursive stack-depth check in the Proxy [[Get]] path.

Trigger (minimal):

var a = new Proxy({length: 2}, {});
a.__proto__ = a;
a[1];  // or Array.prototype.forEach.call(a, ()=>{})

Crash type: stack-overflow (SIGABRT / rc=1)
Component: jerry-core/ecma/operations/ecma-proxy-object.c, ecma_proxy_object_get

JerryScript revision

git hash b706935 on master branch

Build platform

Ubuntu 24.04.4 LTS (Linux 6.8.0-106-generic x86_64)

Build steps
tools/build.py --builddir build-asan --build-type Debug \
  --compile-flag=-fsanitize=address \
  --compile-flag=-fno-omit-frame-pointer \
  --compile-flag=-g \
  --linker-flag=-fsanitize=address
Test case
echo "var a=new Proxy({length:2},{}); a.__proto__=a; a[1];" \
  | ASAN_OPTIONS=halt_on_error=0 build-asan/bin/jerry -
Output
==ERROR: AddressSanitizer: stack-overflow on address 0x7ffc0d0e8ff8
         (pc 0x...bd736195 bp 0x7ffc0d0e9040 sp 0x7ffc0d0e8ff0 T0)
Backtrace
    #0  __asan_stack_malloc_0              [asan_fake_stack.cpp:273]
    #7  ecma_builtin_try_to_instantiate_property
            ecma/builtin-objects/ecma-builtins.c:886
    #8  ecma_op_object_find_own            ecma-objects.c:652
    #9  ecma_op_object_get_with_receiver   ecma-objects.c:819
    #10 ecma_op_object_get                 ecma-objects.c:788
    #11 ecma_op_get_method                 ecma-objects.c:1018
    #12 ecma_op_get_method_by_magic_id     ecma-objects.c:1081
    #13 ecma_validate_proxy_object         ecma-proxy-object.c:248
    #14 ecma_proxy_object_get              ecma-proxy-object.c:1151
    #15 ecma_op_object_get_with_receiver   ecma-objects.c:815   ┐
    #16 ecma_proxy_object_get              ecma-proxy-object.c:1163  │ repeats
    #17 ecma_op_object_get_with_receiver   ecma-objects.c:815   │ ~120×
    #18 ecma_proxy_object_get              ecma-proxy-object.c:1163  ┘
    ... [truncated — frames #15–#251 are the same alternating pair]

SUMMARY: AddressSanitizer: stack-overflow
         ecma-proxy-object.c:1163 in ecma_proxy_object_get

The entry into the cycle is at ecma_validate_proxy_object (ecma-proxy-object.c:248), which calls ecma_op_get_method_by_magic_id to look up the handler trap on the Proxy. Because the Proxy's [[Prototype]] is itself, that lookup re-enters ecma_proxy_object_getecma_op_object_get_with_receiver indefinitely.

Expected behavior

JerryScript should detect the prototype cycle and throw a RangeError , rather than overflowing the native stack. The fix should either reject circular prototype chains in Reflect.setPrototypeOf / Object.setPrototypeOf, or add a recursion-depth counter to ecma_op_object_get_with_receiver.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions