This commit is contained in:
Jarred Sumner
2024-10-31 14:26:19 -07:00
committed by Ben Grant
parent b5ed0f028f
commit 664c080d02
2 changed files with 29 additions and 2 deletions

View File

@@ -1542,7 +1542,7 @@ pub const Blob = struct {
}
}
this.reported_estimated_size = size + (this.content_type.len * @intFromBool(this.content_type_allocated));
this.reported_estimated_size = size + (this.content_type.len * @intFromBool(this.content_type_allocated)) + this.name.byteSlice().len;
}
pub fn estimatedSize(this: *Blob) usize {
@@ -3784,7 +3784,7 @@ pub const Blob = struct {
return true;
}
if (value.isString()) {
this.name.deref();
const old_name = this.name;
this.name = bun.String.tryFromJS(value, globalThis) orelse {
// Handle allocation failure.
@@ -3793,6 +3793,7 @@ pub const Blob = struct {
};
// We don't need to increment the reference count since tryFromJS already did it.
Blob.nameSetCached(jsThis, globalThis, value);
old_name.deref();
return true;
}
return false;
@@ -4181,6 +4182,7 @@ pub const Blob = struct {
} else if (duped.content_type_allocated and duped.allocator != null and include_content_type) {
duped.content_type = bun.default_allocator.dupe(u8, this.content_type) catch bun.outOfMemory();
}
duped.name = duped.name.dupeRef();
duped.allocator = null;
return duped;

View File

@@ -620,4 +620,29 @@ describe("FormData", () => {
expect(fileSlice.size).toBe(result.size);
});
});
// The minimum repro for this was to not call the .name and .type getter on the Blob
// But the crux of the issue is that we called dupe() on the Blob, without also incrementing the reference count of the name string.
// https://github.com/oven-sh/bun/issues/14918
it("should increment reference count of the name string on Blob", async () => {
const buffer = new File([Buffer.from(Buffer.alloc(48 * 1024, "abcdefh").toString("base64"), "base64")], "ok.jpg");
function test() {
let file = new File([buffer], "ok.jpg");
file.name;
file.type;
let formData = new FormData();
formData.append("foo", file);
formData.get("foo");
formData.get("foo")!.name;
formData.get("foo")!.type;
return formData;
}
for (let i = 0; i < 100000; i++) {
test();
if (i % 5000 === 0) {
Bun.gc();
}
}
});
});