mirror of
https://github.com/oven-sh/bun
synced 2026-02-09 10:28:47 +00:00
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user