Skip to content

Commit a676dd7

Browse files
bartlomiejuclaude
andcommitted
fix: heap-use-after-free in create_notification (ASAN)
The upstream crdtp Notification class stores `const char* method_` as a raw pointer without copying. When called from Rust, the CString holding the method name is dropped before AppendSerialized is called, causing a use-after-free detected by ASAN. Replace with OwnedNotification that stores a std::string copy of the method name, reproducing the same CBOR serialization logic. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent bafd041 commit a676dd7

File tree

1 file changed

+33
-1
lines changed

1 file changed

+33
-1
lines changed

src/crdtp_binding.cc

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
// Copyright 2024 the Deno authors. All rights reserved. MIT license.
22

33
#include "support.h"
4+
#include "v8/third_party/inspector_protocol/crdtp/cbor.h"
45
#include "v8/third_party/inspector_protocol/crdtp/dispatch.h"
56
#include "v8/third_party/inspector_protocol/crdtp/frontend_channel.h"
67
#include "v8/third_party/inspector_protocol/crdtp/json.h"
8+
#include "v8/third_party/inspector_protocol/crdtp/parser_handler.h"
79

810
using namespace support;
911
using namespace v8_crdtp;
@@ -259,10 +261,40 @@ Serializable* crdtp__CreateResponse(int call_id, Serializable* params) {
259261
return CreateResponse(call_id, std::move(params_ptr)).release();
260262
}
261263

264+
// Owns a copy of the method string, since upstream Notification stores only
265+
// a raw const char* pointer which leads to use-after-free when the Rust
266+
// CString is dropped before AppendSerialized is called.
267+
class OwnedNotification : public Serializable {
268+
public:
269+
OwnedNotification(const char* method, std::unique_ptr<Serializable> params)
270+
: method_(method), params_(std::move(params)) {}
271+
272+
void AppendSerialized(std::vector<uint8_t>* out) const override {
273+
Status status;
274+
std::unique_ptr<ParserHandler> encoder = cbor::NewCBOREncoder(out, &status);
275+
encoder->HandleMapBegin();
276+
encoder->HandleString8(SpanFrom("method"));
277+
encoder->HandleString8(SpanFrom(method_));
278+
encoder->HandleString8(SpanFrom("params"));
279+
if (params_) {
280+
params_->AppendSerialized(out);
281+
} else {
282+
encoder->HandleMapBegin();
283+
encoder->HandleMapEnd();
284+
}
285+
encoder->HandleMapEnd();
286+
assert(status.ok());
287+
}
288+
289+
private:
290+
std::string method_;
291+
std::unique_ptr<Serializable> params_;
292+
};
293+
262294
Serializable* crdtp__CreateNotification(const char* method,
263295
Serializable* params) {
264296
std::unique_ptr<Serializable> params_ptr(params);
265-
return CreateNotification(method, std::move(params_ptr)).release();
297+
return new OwnedNotification(method, std::move(params_ptr));
266298
}
267299

268300
Serializable* crdtp__CreateErrorNotification(

0 commit comments

Comments
 (0)