Skip to content

Commit e50a9f1

Browse files
authored
nsmd: Remove fuzzer-side validation to allow finding OOB bugs (google#15826)
Simplify validate_nsm_msg_length in fuzzer_helpers.h to only check for the minimum header size, allowing the fuzzer to pass malformed payloads to the decoders. Remove local payload length validation from: - decode_get_histogram_format_resp_fuzzer.cc - decode_get_histogram_data_resp_fuzzer.cc
1 parent 279d2dd commit e50a9f1

3 files changed

Lines changed: 1 addition & 91 deletions

File tree

projects/nsmd/decode_get_histogram_data_resp_fuzzer.cc

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -50,27 +50,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
5050
return 0;
5151
}
5252

53-
uint8_t completion_code = payload[sizeof(struct nsm_msg_hdr) + 1];
54-
if (completion_code == NSM_SUCCESS || completion_code == NSM_ACCEPTED) {
55-
if (payload_len >= sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_get_histogram_data_resp)) {
56-
const struct nsm_get_histogram_data_resp* resp = reinterpret_cast<const struct nsm_get_histogram_data_resp*>(payload + sizeof(struct nsm_msg_hdr));
57-
uint16_t num_of_buckets = le16toh(resp->num_of_buckets);
58-
uint8_t type = resp->bucket_data_type;
59-
size_t elem_size = 1;
60-
switch(type) {
61-
case 0: case 1: elem_size = 1; break;
62-
case 2: case 3: elem_size = 2; break;
63-
case 4: case 5: elem_size = 4; break;
64-
case 6: case 7: elem_size = 8; break;
65-
case 8: elem_size = 4; break; // NvS24_8 is float (4 bytes)
66-
default: elem_size = 1; break;
67-
}
68-
size_t header_size = sizeof(struct nsm_msg_hdr) + offsetof(struct nsm_get_histogram_data_resp, bucket_data);
69-
if (payload_len < header_size || (size_t)num_of_buckets * elem_size > payload_len - header_size) {
70-
return 0;
71-
}
72-
}
73-
}
7453

7554
std::vector<uint8_t> out_buf(65536, 0);
7655
uint8_t fuzz_cc = 0;

projects/nsmd/decode_get_histogram_format_resp_fuzzer.cc

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -50,27 +50,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
5050
return 0;
5151
}
5252

53-
uint8_t completion_code = payload[sizeof(struct nsm_msg_hdr) + 1];
54-
if (completion_code == NSM_SUCCESS || completion_code == NSM_ACCEPTED) {
55-
if (payload_len >= sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_get_histogram_format_resp)) {
56-
const struct nsm_get_histogram_format_resp* resp = reinterpret_cast<const struct nsm_get_histogram_format_resp*>(payload + sizeof(struct nsm_msg_hdr));
57-
uint16_t num_of_buckets = le16toh(resp->metadata.num_of_buckets);
58-
uint8_t type = resp->metadata.bucket_data_type;
59-
size_t elem_size = 1;
60-
switch(type) {
61-
case 0: case 1: elem_size = 1; break;
62-
case 2: case 3: elem_size = 2; break;
63-
case 4: case 5: elem_size = 4; break;
64-
case 6: case 7: elem_size = 8; break;
65-
case 8: elem_size = 4; break; // NvS24_8 is float (4 bytes)
66-
default: elem_size = 1; break;
67-
}
68-
size_t header_size = sizeof(struct nsm_msg_hdr) + offsetof(struct nsm_get_histogram_format_resp, bucket_offsets);
69-
if (payload_len < header_size || (size_t)num_of_buckets * elem_size > payload_len - header_size) {
70-
return 0;
71-
}
72-
}
73-
}
7453

7554
std::vector<uint8_t> out_buf(65536, 0);
7655
uint8_t fuzz_cc = 0;

projects/nsmd/fuzzer_helpers.h

Lines changed: 1 addition & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -25,53 +25,5 @@ extern "C" {
2525

2626
// Validates that the packet actually contains the number of bytes specified in the headers
2727
inline bool validate_nsm_msg_length(const uint8_t* payload, size_t payload_len) {
28-
if (payload_len < sizeof(struct nsm_msg_hdr)) {
29-
return false;
30-
}
31-
const struct nsm_msg_hdr* hdr = reinterpret_cast<const struct nsm_msg_hdr*>(payload);
32-
33-
if (hdr->request) {
34-
// Request v1
35-
if (payload_len >= sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_common_req)) {
36-
const struct nsm_common_req* req = reinterpret_cast<const struct nsm_common_req*>(payload + sizeof(struct nsm_msg_hdr));
37-
uint32_t data_size = req->data_size;
38-
if (payload_len >= sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_common_req) + data_size) {
39-
return true;
40-
}
41-
}
42-
43-
// Request v2
44-
if (payload_len >= sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_common_req_v2)) {
45-
const struct nsm_common_req_v2* req_v2 = reinterpret_cast<const struct nsm_common_req_v2*>(payload + sizeof(struct nsm_msg_hdr));
46-
uint32_t data_size_v2 = le16toh(req_v2->data_size);
47-
if (payload_len >= sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_common_req_v2) + data_size_v2) {
48-
return true;
49-
}
50-
}
51-
return false;
52-
} else {
53-
// Response
54-
if (payload_len < sizeof(struct nsm_msg_hdr) + 2) { // command + completion_code
55-
return false;
56-
}
57-
uint8_t completion_code = payload[sizeof(struct nsm_msg_hdr) + 1];
58-
if (completion_code != NSM_SUCCESS && completion_code != NSM_ACCEPTED) {
59-
// Non-success response
60-
if (payload_len >= sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_common_non_success_resp)) {
61-
return true;
62-
}
63-
return false;
64-
}
65-
66-
// Success response
67-
if (payload_len < sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_common_resp)) {
68-
return false;
69-
}
70-
const struct nsm_common_resp* resp = reinterpret_cast<const struct nsm_common_resp*>(payload + sizeof(struct nsm_msg_hdr));
71-
uint32_t data_size = le16toh(resp->data_size);
72-
if (payload_len >= sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_common_resp) + data_size) {
73-
return true;
74-
}
75-
return false;
76-
}
28+
return payload_len >= sizeof(struct nsm_msg_hdr);
7729
}

0 commit comments

Comments
 (0)