diff options
author | Björn Gustavsson <[email protected]> | 2017-03-06 14:28:31 +0100 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2017-03-14 09:47:40 +0100 |
commit | 3334c0c7b831ecf47738c713fd764eef891a298a (patch) | |
tree | bae651bf04cb7a5dead1a87bc8b6f896c4a23705 /lib/asn1/c_src | |
parent | 7cb3d41d40dbe6d72c8d3f5724b62da088dbf189 (diff) | |
download | otp-3334c0c7b831ecf47738c713fd764eef891a298a.tar.gz otp-3334c0c7b831ecf47738c713fd764eef891a298a.tar.bz2 otp-3334c0c7b831ecf47738c713fd764eef891a298a.zip |
asn1_erl_nif.c: Correct handling of tags >= 16384
Tags number above 16383 were not decoded correctly in
ber_decode_tag().
We could fix the problem, but there does not seem to be any need.
First, the only way that high tag numbers can be created is with
manual tagging; after 1994 manual tagging is no longer recommended.
Second, the ASN.1 playground (http://asn1-playground.oss.com) only
supports tags up to 16383 (the same is presumably true for OSS
Nokalva's other tools).
Therefore, clean up the existing code and make it an explicit
'invalid_tag' error when tags above 13383 are encountered
(instead of an implicit 'wrong_tag' error).
Diffstat (limited to 'lib/asn1/c_src')
-rw-r--r-- | lib/asn1/c_src/asn1_erl_nif.c | 38 |
1 files changed, 21 insertions, 17 deletions
diff --git a/lib/asn1/c_src/asn1_erl_nif.c b/lib/asn1/c_src/asn1_erl_nif.c index b29c9a7ed3..7b7e11b02d 100644 --- a/lib/asn1/c_src/asn1_erl_nif.c +++ b/lib/asn1/c_src/asn1_erl_nif.c @@ -901,31 +901,35 @@ static int ber_decode_tag(ErlNifEnv* env, ERL_NIF_TERM *tag, unsigned char *in_b /* then get the tag number */ if ((tmp_tag = (int) INVMASK(in_buf[*ib_index],ASN1_CLASSFORM)) < 31) { - *tag = enif_make_uint(env, tag_no + tmp_tag); + *tag = enif_make_uint(env, tag_no | tmp_tag); (*ib_index)++; } else { - int n = 0; /* n is used to check that the 64K limit is not - exceeded*/ - /* should check that at least three bytes are left in in-buffer,at least two tag byte and at least one length byte */ if ((*ib_index + 3) > in_buf_len) return ASN1_VALUE_ERROR; (*ib_index)++; - /* The tag is in the following bytes in in_buf as - 1ttttttt 1ttttttt ... 0ttttttt, where the t-bits - is the tag number*/ - /* In practice is the tag size limited to 64K, i.e. 16 bits. If - the tag is greater then 64K return an error */ - while (((tmp_tag = (int) in_buf[*ib_index]) >= 128) && n < 2) { - /* m.s.b. = 1 */ - tag_no = tag_no + (MASK(tmp_tag,ASN1_LONG_TAG) << 7); + /* + * The tag is in the following bytes in in_buf as: + * + * 1ttttttt 0ttttttt + * + * or + * + * 0ttttttt + * + * where the t-bits is the tag number. If the tag does not + * fit in two tag bytes (16K), return an error. + */ + if ((tmp_tag = (int) in_buf[*ib_index]) >= 128) { + tag_no = tag_no | (MASK(tmp_tag,ASN1_LONG_TAG) << 7); (*ib_index)++; - n++; - }; - if ((n == 2) && in_buf[*ib_index] > 3) - return ASN1_TAG_ERROR; /* tag number > 64K */ - tag_no = tag_no + in_buf[*ib_index]; + } + tmp_tag = (int) in_buf[*ib_index]; + if (tmp_tag >= 128) { + return ASN1_TAG_ERROR; /* tag number > 16K */ + } + tag_no = tag_no | tmp_tag; (*ib_index)++; *tag = enif_make_uint(env, tag_no); } |