diff options
author | 2023-07-17 04:17:12 -0700 | |
---|---|---|
committer | 2023-07-17 04:18:43 -0700 | |
commit | 6ca20424d6aee5f68a1383293105473406faad81 (patch) | |
tree | 0a9f088eb91c5cbbf73ebd258dab54a2c9b52985 | |
parent | 36a25c358044b0c9a56a06d8246ae2b5098b3ae4 (diff) | |
download | bun-6ca20424d6aee5f68a1383293105473406faad81.tar.gz bun-6ca20424d6aee5f68a1383293105473406faad81.tar.zst bun-6ca20424d6aee5f68a1383293105473406faad81.zip |
Fix crash in console.log(urlSearchParams) on a URLSearchParams object with a lot of keys
-rw-r--r-- | src/bun.js/bindings/webcore/JSURLSearchParams.cpp | 16 | ||||
-rw-r--r-- | test/js/web/html/URLSearchParams.test.ts | 87 |
2 files changed, 99 insertions, 4 deletions
diff --git a/src/bun.js/bindings/webcore/JSURLSearchParams.cpp b/src/bun.js/bindings/webcore/JSURLSearchParams.cpp index a99587d40..a988b0518 100644 --- a/src/bun.js/bindings/webcore/JSURLSearchParams.cpp +++ b/src/bun.js/bindings/webcore/JSURLSearchParams.cpp @@ -405,7 +405,13 @@ static inline JSC::EncodedJSValue jsURLSearchParamsPrototypeFunction_toJSONBody( auto& impl = castedThis->wrapped(); auto iter = impl.createIterator(); - auto* obj = JSC::constructEmptyObject(lexicalGlobalObject, lexicalGlobalObject->objectPrototype(), impl.size() + 1); + JSObject* obj; + if (impl.size() + 1 < 64) { + obj = JSC::constructEmptyObject(lexicalGlobalObject, lexicalGlobalObject->objectPrototype(), impl.size() + 1); + } else { + obj = JSC::constructEmptyObject(lexicalGlobalObject, lexicalGlobalObject->objectPrototype()); + } + obj->putDirect(vm, vm.propertyNames->toStringTagSymbol, jsNontrivialString(lexicalGlobalObject->vm(), "URLSearchParams"_s), JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::ReadOnly | 0); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); @@ -417,6 +423,9 @@ static inline JSC::EncodedJSValue jsURLSearchParamsPrototypeFunction_toJSONBody( if (seenKeys.contains(key)) { JSValue jsValue = obj->getDirect(vm, ident); if (jsValue.isString()) { + JSValue stringResult = jsString(vm, value); + ensureStillAliveHere(stringResult); + GCDeferralContext deferralContext(lexicalGlobalObject->vm()); JSC::ObjectInitializationScope initializationScope(lexicalGlobalObject->vm()); @@ -426,13 +435,12 @@ static inline JSC::EncodedJSValue jsURLSearchParamsPrototypeFunction_toJSONBody( 2); array->initializeIndex(initializationScope, 0, jsValue); - array->initializeIndex(initializationScope, 1, jsString(vm, value)); + array->initializeIndex(initializationScope, 1, stringResult); obj->putDirect(vm, ident, array, 0); - } else if (jsValue.isObject() && jsValue.getObject()->inherits<JSC::JSArray>()) { + } else if (jsValue.isCell() && jsValue.asCell()->type() == ArrayType) { JSC::JSArray* array = jsCast<JSC::JSArray*>(jsValue.getObject()); array->push(lexicalGlobalObject, jsString(vm, value)); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); - } else { RELEASE_ASSERT_NOT_REACHED(); } diff --git a/test/js/web/html/URLSearchParams.test.ts b/test/js/web/html/URLSearchParams.test.ts index 41c42c25d..a948af821 100644 --- a/test/js/web/html/URLSearchParams.test.ts +++ b/test/js/web/html/URLSearchParams.test.ts @@ -1,6 +1,93 @@ import { describe, it, expect } from "bun:test"; describe("URLSearchParams", () => { + it("does not crash when calling .toJSON() on a URLSearchParams object with a large number of properties", () => { + const props = { + "id": "1296269", + "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5", + "name": "Hello-World", + "full_name": "octocat/Hello-World", + "owner": "[object Object]", + "private": "false", + "html_url": "https://github.com/octocat/Hello-World", + "description": "This your first repo!", + "fork": "false", + "url": "https://api.github.com/repos/octocat/Hello-World", + "archive_url": "https://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}", + "assignees_url": "https://api.github.com/repos/octocat/Hello-World/assignees{/user}", + "blobs_url": "https://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}", + "branches_url": "https://api.github.com/repos/octocat/Hello-World/branches{/branch}", + "collaborators_url": "https://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}", + "comments_url": "https://api.github.com/repos/octocat/Hello-World/comments{/number}", + "commits_url": "https://api.github.com/repos/octocat/Hello-World/commits{/sha}", + "compare_url": "https://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}", + "contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/{+path}", + "contributors_url": "https://api.github.com/repos/octocat/Hello-World/contributors", + "deployments_url": "https://api.github.com/repos/octocat/Hello-World/deployments", + "downloads_url": "https://api.github.com/repos/octocat/Hello-World/downloads", + "events_url": "https://api.github.com/repos/octocat/Hello-World/events", + "forks_url": "https://api.github.com/repos/octocat/Hello-World/forks", + "git_commits_url": "https://api.github.com/repos/octocat/Hello-World/git/commits{/sha}", + "git_refs_url": "https://api.github.com/repos/octocat/Hello-World/git/refs{/sha}", + "git_tags_url": "https://api.github.com/repos/octocat/Hello-World/git/tags{/sha}", + "git_url": "git:github.com/octocat/Hello-World.git", + "issue_comment_url": "https://api.github.com/repos/octocat/Hello-World/issues/comments{/number}", + "issue_events_url": "https://api.github.com/repos/octocat/Hello-World/issues/events{/number}", + "issues_url": "https://api.github.com/repos/octocat/Hello-World/issues{/number}", + "keys_url": "https://api.github.com/repos/octocat/Hello-World/keys{/key_id}", + "labels_url": "https://api.github.com/repos/octocat/Hello-World/labels{/name}", + "languages_url": "https://api.github.com/repos/octocat/Hello-World/languages", + "merges_url": "https://api.github.com/repos/octocat/Hello-World/merges", + "milestones_url": "https://api.github.com/repos/octocat/Hello-World/milestones{/number}", + "notifications_url": "https://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}", + "pulls_url": "https://api.github.com/repos/octocat/Hello-World/pulls{/number}", + "releases_url": "https://api.github.com/repos/octocat/Hello-World/releases{/id}", + "ssh_url": "git@github.com:octocat/Hello-World.git", + "stargazers_url": "https://api.github.com/repos/octocat/Hello-World/stargazers", + "statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/{sha}", + "subscribers_url": "https://api.github.com/repos/octocat/Hello-World/subscribers", + "subscription_url": "https://api.github.com/repos/octocat/Hello-World/subscription", + "tags_url": "https://api.github.com/repos/octocat/Hello-World/tags", + "teams_url": "https://api.github.com/repos/octocat/Hello-World/teams", + "trees_url": "https://api.github.com/repos/octocat/Hello-World/git/trees{/sha}", + "clone_url": "https://github.com/octocat/Hello-World.git", + "mirror_url": "git:git.example.com/octocat/Hello-World", + "hooks_url": "https://api.github.com/repos/octocat/Hello-World/hooks", + "svn_url": "https://svn.github.com/octocat/Hello-World", + "homepage": "https://github.com", + "language": "null", + "forks_count": "9", + "stargazers_count": "80", + "watchers_count": "80", + "size": "108", + "default_branch": "master", + "open_issues_count": "0", + "is_template": "false", + "topics": "octocat,atom,electron,api", + "has_issues": "true", + "has_projects": "true", + "has_wiki": "true", + "has_pages": "false", + "has_downloads": "true", + "has_discussions": "false", + "archived": "false", + "disabled": "false", + "visibility": "public", + "pushed_at": "2011-01-26T19:06:43Z", + "created_at": "2011-01-26T19:01:12Z", + "updated_at": "2011-01-26T19:14:43Z", + "permissions": "[object Object]", + "security_and_analysis": "[object Object]", + }; + var params = new URLSearchParams(); + for (const key in props) { + params.set(key, props[key as keyof typeof props]); + } + + // @ts-expect-error + expect(params.toJSON()).toEqual(props); + }); + describe("non-standard extensions", () => { it("should support .length", () => { const params = new URLSearchParams(); |