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

Maximum call stack size exceeded during encryptString #5624

Closed
ahoyahoy opened this issue Feb 10, 2024 · 14 comments
Closed

Maximum call stack size exceeded during encryptString #5624

ahoyahoy opened this issue Feb 10, 2024 · 14 comments

Comments

@ahoyahoy
Copy link

ahoyahoy commented Feb 10, 2024

minimal example https://github.com/ahoyahoy/rxdb-shared-worker-error/blob/crypto/src/main.ts#L41C7-L41C19
crypto branch

There is a "long" string okText.
I found one document that caused me a problem during data replication.
I gradually deleted all the props from it until there were only a few left (similar) and they together caused a problem, if I deleted one of them, no problem.
But I found that even if I take just one of them and repeat it a few times, I get the same problem. see strangeText

With this string I'm getting this error

helpers.js:1 Uncaught (in promise) RangeError: Maximum call stack size exceeded
at ab2b64 (helpers.js:1:1187)
at encryptString (helpers.js:1:1376)

I also tried to make much longer random string and no problem.

"rxdb": "15.7.0",
"rxdb-premium": "15.7.0",

@ahoyahoy
Copy link
Author

this only happens when using wrappedKeyEncryptionWebCryptoStorage in the worker instead of the main thread

@pubkey
Copy link
Owner

pubkey commented Feb 11, 2024

Could reproduce but atm I have no idea what is going on here.
ab2b64 is basically just calling js-base64

export function ab2b64(arrayBuffer: ArrayBuffer): string {
    return b64EncodeUnicode(String.fromCharCode.apply(null, new Uint8Array(arrayBuffer) as any));
}

import { encode, decode } from 'js-base64';

/**
 * atob() and btoa() do not work well with non ascii chars,
 * so we have to use these helper methods instead.
 * @link https://stackoverflow.com/a/30106551/3443137
 */
// Encoding UTF8 -> base64
export function b64EncodeUnicode(str: string) {
    return encode(str);
}

@pubkey
Copy link
Owner

pubkey commented Feb 11, 2024

I think this error only occurs inside of the worker, because web workers have a small max stack size.

Using const strangeText = okText.repeat(8); produces the same error even when using indexeddb and encryption in the main thread only without a worker.

Also calling js-base64 encode directly causes the same error:

import { encode } from 'js-base64';
const strangeText = okText.repeat(8);
encode(strangeText);

I was not sure if I can share your demo-code string so please create an issue or make a PR at the js-base64 repo.

@ahoyahoy
Copy link
Author

ahoyahoy commented Feb 12, 2024

hm it's weird
I tried this encode in node, browser and Vite and no problem (3 different stackblitz)

I also tried repeat(1000)

https://stackblitz.com/edit/vitejs-vite-brcepd?file=src%2Fmain.ts

@pubkey
Copy link
Owner

pubkey commented Feb 12, 2024

This is so strange. Running your example also works for me. I also added base64-js via cdn to a plain html file and run the code which worked. Only in my karma-browserify test setup it fails (newest chrome).

@ahoyahoy
Copy link
Author

Probably the error is not in my specific string and its repetition, but in the length of the document.
With this randomly generated text, it will reliably return an error above 125 kB of text.

function generateRandomString(length) {
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let result = '';
const charactersLength = characters.length;
for (let i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}

const randomText = generateRandomString(1000 * 125); // ok

in main thread ×126 will cause an error

in shared worker it's ×63 max

@ahoyahoy
Copy link
Author

maybe you have to split arrayBuffer into smaller chunks?

@ahoyahoy
Copy link
Author

@pubkey
Copy link
Owner

pubkey commented Feb 14, 2024

@ahoyahoy

With this randomly generated text, it will reliably return an error above 125 kB of text.

I could not reliably reproduce that with the plain base64-js encode function. Can you make a stackbliz with that?

I tried this but this does not show the error: https://stackblitz.com/edit/vitejs-vite-ggmddh?file=src%2Fmain.ts

@ahoyahoy
Copy link
Author

yes, because the problem is with Uint8Array not base64-js

I updated this example https://stackblitz.com/edit/vitejs-vite-kgrb6y?file=src%2Fmain.ts

see the line 56
const strFromAb = ab2b64WithoutEncode(ab);

if you make randomText longer (more than 125), it will fail

@pubkey
Copy link
Owner

pubkey commented Feb 14, 2024

But where is ab2b64WithoutEncode from? Because it is neither used in rxdb nor in js-base64.
Shouldnt then calling base64-js encode() also fail with the same error on the same input?

@ahoyahoy
Copy link
Author

its your function without b64EncodeUnicode (updated by me)
export function ab2b64(arrayBuffer: ArrayBuffer): string {
return b64EncodeUnicode(String.fromCharCode.apply(null, new Uint8Array(arrayBuffer) as any));
}
just for test in your code
#5624 (comment)

@pubkey
Copy link
Owner

pubkey commented Feb 14, 2024

@ahoyahoy Can you try the latest release? This should be fixed now, I added your proposed chunking to prevent the error.
Thank you for your time and investigations, that helped a lot.

@ahoyahoy
Copy link
Author

it works, thanks :)

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

No branches or pull requests

2 participants