mirror of
https://github.com/oven-sh/bun
synced 2026-02-12 11:59:00 +00:00
* Fixes #3250 We must call `EVP_MD_CTX_cleanup` because `EVP_MD_CTX` containers pointers inside to allocated memory * Fix leak * Update sha.zig --------- Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
This commit is contained in:
@@ -1533,7 +1533,6 @@ pub const Crypto = struct {
|
||||
var ctx: BoringSSL.EVP_MD_CTX = undefined;
|
||||
BoringSSL.EVP_MD_CTX_init(&ctx);
|
||||
_ = BoringSSL.EVP_DigestInit_ex(&ctx, md, engine);
|
||||
|
||||
return .{
|
||||
.ctx = ctx,
|
||||
.md = md,
|
||||
@@ -1615,6 +1614,11 @@ pub const Crypto = struct {
|
||||
defer name_str.deinit();
|
||||
return byNameAndEngine(global.bunVM().rareData().boringEngine(), name_str.slice());
|
||||
}
|
||||
|
||||
pub fn deinit(this: *EVP) void {
|
||||
// https://github.com/oven-sh/bun/issues/3250
|
||||
_ = BoringSSL.EVP_MD_CTX_cleanup(&this.ctx);
|
||||
}
|
||||
};
|
||||
|
||||
fn createCryptoError(globalThis: *JSC.JSGlobalObject, err_code: u32) JSValue {
|
||||
@@ -1867,6 +1871,7 @@ pub const Crypto = struct {
|
||||
// we use SHA512 to hash the password if it's longer than 72 bytes
|
||||
if (password.len > 72) {
|
||||
var sha_256 = bun.sha.SHA512.init();
|
||||
defer sha_256.deinit();
|
||||
sha_256.update(password);
|
||||
sha_256.final(outbuf[0..bun.sha.SHA512.digest]);
|
||||
password_to_use = outbuf[0..bun.sha.SHA512.digest];
|
||||
@@ -2469,10 +2474,11 @@ pub const Crypto = struct {
|
||||
fn hashToEncoding(
|
||||
globalThis: *JSGlobalObject,
|
||||
evp: *EVP,
|
||||
input: JSC.Node.StringOrBuffer,
|
||||
input: JSC.Node.SliceOrBuffer,
|
||||
encoding: JSC.Node.Encoding,
|
||||
) JSC.JSValue {
|
||||
var output_digest_buf: Digest = undefined;
|
||||
defer input.deinit();
|
||||
|
||||
const len = evp.hash(globalThis.bunVM().rareData().boringEngine(), input.slice(), &output_digest_buf) orelse {
|
||||
const err = BoringSSL.ERR_get_error();
|
||||
@@ -2487,11 +2493,12 @@ pub const Crypto = struct {
|
||||
fn hashToBytes(
|
||||
globalThis: *JSGlobalObject,
|
||||
evp: *EVP,
|
||||
input: JSC.Node.StringOrBuffer,
|
||||
input: JSC.Node.SliceOrBuffer,
|
||||
output: ?JSC.ArrayBuffer,
|
||||
) JSC.JSValue {
|
||||
var output_digest_buf: Digest = undefined;
|
||||
var output_digest_slice: []u8 = &output_digest_buf;
|
||||
defer input.deinit();
|
||||
if (output) |output_buf| {
|
||||
const size = evp.size();
|
||||
var bytes = output_buf.byteSlice();
|
||||
@@ -2513,21 +2520,22 @@ pub const Crypto = struct {
|
||||
if (output) |output_buf| {
|
||||
return output_buf.value;
|
||||
} else {
|
||||
var array_buffer_out = JSC.ArrayBuffer.fromBytes(bun.default_allocator.dupe(u8, output_digest_slice[0..len]) catch unreachable, .Uint8Array);
|
||||
return array_buffer_out.toJSUnchecked(globalThis, null);
|
||||
// Clone to GC-managed memory
|
||||
return JSC.ArrayBuffer.create(globalThis, output_digest_slice[0..len], .Buffer);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hash_(
|
||||
globalThis: *JSGlobalObject,
|
||||
algorithm: ZigString,
|
||||
input: JSC.Node.StringOrBuffer,
|
||||
input: JSC.Node.SliceOrBuffer,
|
||||
output: ?JSC.Node.StringOrBuffer,
|
||||
) JSC.JSValue {
|
||||
var evp = EVP.byName(algorithm, globalThis) orelse {
|
||||
globalThis.throwInvalidArguments("Unsupported algorithm \"{any}\"", .{algorithm});
|
||||
return .zero;
|
||||
};
|
||||
defer evp.deinit();
|
||||
|
||||
if (output) |string_or_buffer| {
|
||||
switch (string_or_buffer) {
|
||||
@@ -2624,13 +2632,14 @@ pub const Crypto = struct {
|
||||
pub fn digest_(
|
||||
this: *@This(),
|
||||
globalThis: *JSGlobalObject,
|
||||
output: ?JSC.Node.StringOrBuffer,
|
||||
output: ?JSC.Node.SliceOrBuffer,
|
||||
) JSC.JSValue {
|
||||
if (output) |string_or_buffer| {
|
||||
switch (string_or_buffer) {
|
||||
.string => |str| {
|
||||
const encoding = JSC.Node.Encoding.from(str) orelse {
|
||||
globalThis.throwInvalidArguments("Unknown encoding: {s}", .{str});
|
||||
defer str.deinit();
|
||||
const encoding = JSC.Node.Encoding.from(str.slice()) orelse {
|
||||
globalThis.throwInvalidArguments("Unknown encoding: {}", .{str});
|
||||
return JSC.JSValue.zero;
|
||||
};
|
||||
|
||||
@@ -2667,8 +2676,8 @@ pub const Crypto = struct {
|
||||
if (output) |output_buf| {
|
||||
return output_buf.value;
|
||||
} else {
|
||||
var array_buffer_out = JSC.ArrayBuffer.fromBytes(bun.default_allocator.dupe(u8, result) catch unreachable, .Uint8Array);
|
||||
return array_buffer_out.toJSUnchecked(globalThis, null);
|
||||
// Clone to GC-managed memory
|
||||
return JSC.ArrayBuffer.create(globalThis, result, .Buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2683,7 +2692,10 @@ pub const Crypto = struct {
|
||||
}
|
||||
|
||||
pub fn finalize(this: *CryptoHasher) callconv(.C) void {
|
||||
VirtualMachine.get().allocator.destroy(this);
|
||||
// https://github.com/oven-sh/bun/issues/3250
|
||||
this.evp.deinit();
|
||||
|
||||
bun.default_allocator.destroy(this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -3125,6 +3125,29 @@ pub fn wrapStaticMethod(
|
||||
args[i] = null;
|
||||
}
|
||||
},
|
||||
JSC.Node.SliceOrBuffer => {
|
||||
const arg = iter.nextEat() orelse {
|
||||
globalThis.throwInvalidArguments("expected string or buffer", .{});
|
||||
iter.deinit();
|
||||
return JSC.JSValue.zero;
|
||||
};
|
||||
args[i] = JSC.Node.SliceOrBuffer.fromJS(globalThis.ptr(), iter.arena.allocator(), arg) orelse {
|
||||
globalThis.throwInvalidArguments("expected string or buffer", .{});
|
||||
iter.deinit();
|
||||
return JSC.JSValue.zero;
|
||||
};
|
||||
},
|
||||
?JSC.Node.SliceOrBuffer => {
|
||||
if (iter.nextEat()) |arg| {
|
||||
args[i] = JSC.Node.SliceOrBuffer.fromJS(globalThis.ptr(), iter.arena.allocator(), arg) orelse {
|
||||
globalThis.throwInvalidArguments("expected string or buffer", .{});
|
||||
iter.deinit();
|
||||
return JSC.JSValue.zero;
|
||||
};
|
||||
} else {
|
||||
args[i] = null;
|
||||
}
|
||||
},
|
||||
JSC.ArrayBuffer => {
|
||||
if (iter.nextEat()) |arg| {
|
||||
args[i] = arg.asArrayBuffer(globalThis.ptr()) orelse {
|
||||
|
||||
@@ -74,6 +74,10 @@ fn NewEVP(
|
||||
pub fn final(this: *@This(), out: *Digest) void {
|
||||
std.debug.assert(BoringSSL.EVP_DigestFinal(&this.ctx, out, null) == 1);
|
||||
}
|
||||
|
||||
pub fn deinit(this: *@This()) void {
|
||||
_ = BoringSSL.EVP_MD_CTX_cleanup(&this.ctx);
|
||||
}
|
||||
};
|
||||
}
|
||||
pub const EVP = struct {
|
||||
@@ -331,4 +335,3 @@ pub fn main() anyerror!void {
|
||||
// std.crypto.hash.sha2.Sha256.hash(value, &hash2, .{});
|
||||
// try std.testing.expectEqual(hash, hash2);
|
||||
// }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user