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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions