Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions libr/util/asn1.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ static RASN1Object *asn1_parse_header(const ut8 *buffer_base, const ut8 *buffer,
// Check for indefinite length.
if (length8) {
// Length over 6 bytes is not allowed.
if (length8 > length - 1 || length8 > 6) {
if (length8 > length - 2 || length8 > 6) {
R_LOG_DEBUG ("ASN.1: length error");
goto out_error;
}
Expand Down Expand Up @@ -83,7 +83,7 @@ static RASN1Object *asn1_parse_header(const ut8 *buffer_base, const ut8 *buffer,
// Calculate headerlength before BITSTRING adjustment
obj->headerlength = obj->sector - initial_pos;
if (obj->tag == TAG_BITSTRING) {
if (obj->length > 0) {
if (obj->length > 0 && obj->sector < buffer + length) {
obj->length--;
obj->bitlength = obj->length * 8 - obj->sector[0];
obj->sector++; // real sector starts + 1
Expand Down
1 change: 1 addition & 0 deletions test/unit/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ if get_option('enable_tests')
'anal_xrefs',
'anal_x86',
'arena',
'asn1',
'axml',
'codemeta',
'base64',
Expand Down
41 changes: 41 additions & 0 deletions test/unit/test_asn1.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include <r_util.h>
#include "minunit.h"

// long-form length-of-length that claims more length octets than the buffer
// holds: with a 3 byte buffer and two length octets the parser used to read
// buffer[3], one past the end.
bool test_asn1_longform_length_oob(void) {
ut8 *buf = malloc (3);
buf[0] = 0x30; // SEQUENCE
buf[1] = 0x82; // long form, two length octets
buf[2] = 0x00;
RASN1Object *o = r_asn1_object_parse (buf, buf, 3, 0);
mu_assert_null (o, "long-form length with more octets than the buffer holds must be rejected");
r_asn1_object_free (o);
free (buf);
mu_end;
}

// bitstring whose declared content starts exactly at the end of the buffer:
// the unused-bits byte (sector[0]) used to be read one past the end.
bool test_asn1_bitstring_sector_oob(void) {
ut8 *buf = malloc (3);
buf[0] = 0x23; // BITSTRING
buf[1] = 0x81; // long form, one length octet
buf[2] = 0x01; // length 1, so the content byte lands past the buffer
RASN1Object *o = r_asn1_object_parse (buf, buf, 3, 0);
mu_assert_notnull (o, "truncated bitstring should still parse without reading past the buffer");
r_asn1_object_free (o);
free (buf);
mu_end;
}

int all_tests(void) {
mu_run_test (test_asn1_longform_length_oob);
mu_run_test (test_asn1_bitstring_sector_oob);
return tests_passed != tests_run;
}

int main(int argc, char **argv) {
return all_tests ();
}
Loading