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

Infinite loop in encode.js #2098

Open
4 tasks done
ajmeese7 opened this issue Mar 24, 2024 · 5 comments · May be fixed by #2099
Open
4 tasks done

Infinite loop in encode.js #2098

ajmeese7 opened this issue Mar 24, 2024 · 5 comments · May be fixed by #2099
Labels
type:bug Impaired feature or lacking behavior that is likely assumed

Comments

@ajmeese7
Copy link

New Issue Checklist

Issue Description

The encode function is called recursively without a ceiling, causing the entire service to crash with no hint as to the originating call, even with VERBOSE=1 enabled. All I know is that the error is thrown from this line:

if (value && typeof value === 'object') {
  const output = {};
  for (const k in value) {
+   output[k] = encode(value[k], disallowObjects, forcePointers, seen, offline);
  }
  return output;
}

Steps to reproduce

Unsure, inherited legacy code and there is no hint as to which network call is causing this issue.

Actual Outcome

Program errors out without any hint as to where the error is coming from.

Expected Outcome

The function to execute properly. Two possible improvements to the library come to mind:

  1. Give further context about where the error is coming from
  2. Have a limit on the number of calls within the function and truncate after the limit is hit, giving a warning in the console but not causing the program to error out

Environment

Server

  • Parse Server version: 7.0.0
  • Operating system: node:18 Docker image
  • Local or remote host (AWS, Azure, Google Cloud, Heroku, Digital Ocean, etc): Local

Database

  • System (MongoDB or Postgres): MongoDB
  • Database version: 5.9.2
  • Local or remote host (MongoDB Atlas, mLab, AWS, Azure, Google Cloud, etc): Local

Client

  • Parse JS SDK version: 5.0.0

Logs

An uncaught exception occurred: Maximum call stack size exceededStack Trace:
RangeError: Maximum call stack size exceeded
    at encode (/api/node_modules/.pnpm/parse@5.0.0/node_modules/parse/lib/node/encode.js:23:16)
    at /api/node_modules/.pnpm/parse@5.0.0/node_modules/parse/lib/node/encode.js:61:14
    at Array.map (<anonymous>)
    at encode (/api/node_modules/.pnpm/parse@5.0.0/node_modules/parse/lib/node/encode.js:60:18)
    at encode (/api/node_modules/.pnpm/parse@5.0.0/node_modules/parse/lib/node/encode.js:67:19)
    at encode (/api/node_modules/.pnpm/parse@5.0.0/node_modules/parse/lib/node/encode.js:67:19)
    at encode (/api/node_modules/.pnpm/parse@5.0.0/node_modules/parse/lib/node/encode.js:67:19)
    at encode (/api/node_modules/.pnpm/parse@5.0.0/node_modules/parse/lib/node/encode.js:67:19)
    at encode (/api/node_modules/.pnpm/parse@5.0.0/node_modules/parse/lib/node/encode.js:67:19)
Copy link

Thanks for opening this issue!

  • 🚀 You can help us to fix this issue faster by opening a pull request with a failing test. See our Contribution Guide for how to make a pull request, or read our New Contributor's Guide if this is your first time contributing.

@mtrezza
Copy link
Member

mtrezza commented Mar 24, 2024

Have a limit on the number of calls within the function and truncate after the limit is hit, giving a warning in the console but not causing the program to error out

Not sure about warning; this is such a general method that encodes a Parse Object; we wouldn't know what exactly the effect is if we just "truncate" the encoding of an object. I believe encoding should fail after n iterations, whatever we decide a reasonable n to be, causing the calling method to fail and produce an error. To determine a reasonable n we would need to better understand in which cases a recursive calling happens.

As to your specific case, if you add a limit with n say 1000 and then let the calling op fail and log a detailed error, then you would also know what was causing this. Such a limit should be easy to implement. If you open a PR, then we can release it as alpha version, you can test it out in production and see what's causing this.

@mtrezza mtrezza added the type:bug Impaired feature or lacking behavior that is likely assumed label Mar 24, 2024
@ajmeese7 ajmeese7 linked a pull request Mar 25, 2024 that will close this issue
@dplewis
Copy link
Member

dplewis commented Mar 29, 2024

I have run into this issue as well returning objects from a certain API in Cloud Code functions. I deconstructed the object manually or find if the object has a toJSON() function and return it.

In cloud code you can basically return anything. If it happens to be to an object with circular references then you will run into this issue.

Parse.Cloud.define('Circular', () => {
  const a = {};
  const b = {};
  a.b = b;
  b.a = a;
  return a;
  // const object = new Parse.Object('Test');
  // object.set('a', a);
  // return object.save()
});

mtrezza added a commit to ajmeese7/Parse-SDK-JS that referenced this issue Apr 1, 2024
@ajmeese7
Copy link
Author

ajmeese7 commented Apr 3, 2024

Whenever I used the logging currently added in the PR, this is the output I got:

2024-04-03 10:51:12 Encoding object failed due to high number of recursive calls, likely caused by circular reference within object.
2024-04-03 10:51:12 Value causing potential infinite recursion: 4184
2024-04-03 10:51:12 Disallow objects: false
2024-04-03 10:51:12 Force pointers: false
2024-04-03 10:51:12 Seen: []
2024-04-03 10:51:12 Offline: undefined
2024-04-03 10:51:12 An uncaught exception occurred: Encoding object failed due to high number of recursive calls, likely caused by circular reference within object.Stack Trace:
2024-04-03 10:51:12 Error: Encoding object failed due to high number of recursive calls, likely caused by circular reference within object.
2024-04-03 10:51:12     at encode (/api/node_modules/.pnpm/parse@5.0.0/node_modules/parse/lib/node/encode.js:34:11)
2024-04-03 10:51:12     at encode (/api/node_modules/.pnpm/parse@5.0.0/node_modules/parse/lib/node/encode.js:79:19)
2024-04-03 10:51:12     at encode (/api/node_modules/.pnpm/parse@5.0.0/node_modules/parse/lib/node/encode.js:79:19)
2024-04-03 10:51:12     at encode (/api/node_modules/.pnpm/parse@5.0.0/node_modules/parse/lib/node/encode.js:79:19)
2024-04-03 10:51:12     at encode (/api/node_modules/.pnpm/parse@5.0.0/node_modules/parse/lib/node/encode.js:79:19)
2024-04-03 10:51:12     at encode (/api/node_modules/.pnpm/parse@5.0.0/node_modules/parse/lib/node/encode.js:79:19)
2024-04-03 10:51:12     at encode (/api/node_modules/.pnpm/parse@5.0.0/node_modules/parse/lib/node/encode.js:79:19)
2024-04-03 10:51:12     at encode (/api/node_modules/.pnpm/parse@5.0.0/node_modules/parse/lib/node/encode.js:79:19)
2024-04-03 10:51:12     at encode (/api/node_modules/.pnpm/parse@5.0.0/node_modules/parse/lib/node/encode.js:79:19)

Does this make sense to you at all? I'm not sure why some number would cause this issue, or if that's just the console doing a bad job of stringifying whatever the object in question is. In case it was the stringifying, I changed the print code to:

console.error('Value causing potential infinite recursion:', JSON.stringify(value, null, 4));

And the next run's output was Value causing potential infinite recursion: 266328, which again provides very little information and no valuable intel to act on.

@mtrezza
Copy link
Member

mtrezza commented Apr 3, 2024

I'd like to point to my comment. Maybe it makes sense to properly handle circular references, instead of causing a stack overflow.

mtrezza added a commit to ajmeese7/Parse-SDK-JS that referenced this issue Apr 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type:bug Impaired feature or lacking behavior that is likely assumed
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants