forked from acouzens/open5gs
[ASN.1] Fix buffer overflow (mouse07410/asn1c#134) (#2742)
This commit is contained in:
parent
d2f2fa0402
commit
9479f29f3d
|
@ -6,21 +6,15 @@
|
||||||
#include <asn_internal.h>
|
#include <asn_internal.h>
|
||||||
#include <BIT_STRING.h>
|
#include <BIT_STRING.h>
|
||||||
|
|
||||||
static const char *_bit_pattern[16] = {
|
|
||||||
"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111",
|
|
||||||
"1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"
|
|
||||||
};
|
|
||||||
|
|
||||||
asn_enc_rval_t
|
asn_enc_rval_t
|
||||||
BIT_STRING_encode_jer(const asn_TYPE_descriptor_t *td, const void *sptr,
|
BIT_STRING_encode_jer(const asn_TYPE_descriptor_t *td, const void *sptr,
|
||||||
int ilevel, enum jer_encoder_flags_e flags,
|
int ilevel, enum jer_encoder_flags_e flags,
|
||||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||||
asn_enc_rval_t er = {0, 0, 0};
|
asn_enc_rval_t er = {0, 0, 0};
|
||||||
char scratch[128];
|
const char * const h2c = "0123456789ABCDEF";
|
||||||
|
char scratch[16 * 3 + 4];
|
||||||
char *p = scratch;
|
char *p = scratch;
|
||||||
char *scend = scratch + (sizeof(scratch) - 10);
|
|
||||||
const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
|
const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
|
||||||
int xcan = 0;
|
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
uint8_t *end;
|
uint8_t *end;
|
||||||
|
|
||||||
|
@ -33,36 +27,32 @@ BIT_STRING_encode_jer(const asn_TYPE_descriptor_t *td, const void *sptr,
|
||||||
end = buf + st->size - 1; /* Last byte is special */
|
end = buf + st->size - 1; /* Last byte is special */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Binary dump
|
* Hex dump
|
||||||
*/
|
*/
|
||||||
for(; buf < end; buf++) {
|
*p++ = '"';
|
||||||
int v = *buf;
|
for(int i = 0; buf < end; buf++, i++) {
|
||||||
int nline = xcan?0:(((buf - st->buf) % 8) == 0);
|
if(!(i % 16) && (i || st->size > 16)) {
|
||||||
if(p >= scend || nline) {
|
ASN__CALLBACK(scratch, p-scratch);
|
||||||
ASN__CALLBACK(scratch, p - scratch);
|
|
||||||
p = scratch;
|
p = scratch;
|
||||||
if(nline) ASN__TEXT_INDENT(1, ilevel);
|
|
||||||
}
|
}
|
||||||
memcpy(p + 0, _bit_pattern[v >> 4], 4);
|
*p++ = h2c[*buf >> 4];
|
||||||
memcpy(p + 4, _bit_pattern[v & 0x0f], 4);
|
*p++ = h2c[*buf & 0x0F];
|
||||||
p += 8;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!xcan && ((buf - st->buf) % 8) == 0)
|
|
||||||
ASN__TEXT_INDENT(1, ilevel);
|
|
||||||
ASN__CALLBACK(scratch, p - scratch);
|
ASN__CALLBACK(scratch, p - scratch);
|
||||||
p = scratch;
|
p = scratch;
|
||||||
|
|
||||||
if(buf == end) {
|
if(buf == end) {
|
||||||
int v = *buf;
|
|
||||||
int ubits = st->bits_unused;
|
int ubits = st->bits_unused;
|
||||||
int i;
|
uint8_t v = *buf & (0xff << ubits);
|
||||||
for(i = 7; i >= ubits; i--)
|
*p++ = h2c[v >> 4];
|
||||||
*p++ = (v & (1 << i)) ? 0x31 : 0x30;
|
*p++ = h2c[v & 0x0F];
|
||||||
ASN__CALLBACK(scratch, p - scratch);
|
ASN__CALLBACK(scratch, p - scratch);
|
||||||
|
p = scratch;
|
||||||
}
|
}
|
||||||
|
*p++ = '"';
|
||||||
if(!xcan) ASN__TEXT_INDENT(1, ilevel - 1);
|
ASN__CALLBACK(scratch, p - scratch);
|
||||||
|
ASN__TEXT_INDENT(1, ilevel - 1);
|
||||||
|
|
||||||
ASN__ENCODED_OK(er);
|
ASN__ENCODED_OK(er);
|
||||||
cb_failed:
|
cb_failed:
|
||||||
|
|
|
@ -30,22 +30,19 @@ OCTET_STRING_encode_jer(const asn_TYPE_descriptor_t *td, const void *sptr,
|
||||||
*/
|
*/
|
||||||
buf = st->buf;
|
buf = st->buf;
|
||||||
end = buf + st->size;
|
end = buf + st->size;
|
||||||
|
ASN__CALLBACK("\"", 1);
|
||||||
for(i = 0; buf < end; buf++, i++) {
|
for(i = 0; buf < end; buf++, i++) {
|
||||||
if(!(i % 16) && (i || st->size > 16)) {
|
if(!(i % 16) && (i || st->size > 16)) {
|
||||||
ASN__CALLBACK(scratch, p-scratch);
|
ASN__CALLBACK(scratch, p-scratch);
|
||||||
p = scratch;
|
p = scratch;
|
||||||
ASN__TEXT_INDENT(1, ilevel);
|
|
||||||
}
|
}
|
||||||
*p++ = h2c[(*buf >> 4) & 0x0F];
|
*p++ = h2c[(*buf >> 4) & 0x0F];
|
||||||
*p++ = h2c[*buf & 0x0F];
|
*p++ = h2c[*buf & 0x0F];
|
||||||
*p++ = 0x20;
|
|
||||||
}
|
}
|
||||||
if(p - scratch) {
|
if(p - scratch) {
|
||||||
p--; /* Remove the tail space */
|
ASN__CALLBACK(scratch, p-scratch); /* Dump the rest */
|
||||||
ASN__CALLBACK3("\"", 1, scratch, p-scratch, "\"", 1); /* Dump the rest */
|
|
||||||
if(st->size > 16)
|
|
||||||
ASN__TEXT_INDENT(1, ilevel-1);
|
|
||||||
}
|
}
|
||||||
|
ASN__CALLBACK("\"", 1);
|
||||||
|
|
||||||
ASN__ENCODED_OK(er);
|
ASN__ENCODED_OK(er);
|
||||||
cb_failed:
|
cb_failed:
|
||||||
|
|
|
@ -179,8 +179,25 @@ asn__format_to_callback(
|
||||||
/*
|
/*
|
||||||
* Check stack against overflow, if limit is set.
|
* Check stack against overflow, if limit is set.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Since GCC 13, AddressSanitizer started defaulting to
|
||||||
|
* ASAN_OPTIONS="detect_stack_use_after_return=1", which makes this check
|
||||||
|
* fail due to apparently jumping stack pointers.
|
||||||
|
* Hence, disable this check if building with ASan, as documented in:
|
||||||
|
* GCC: https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
|
||||||
|
* Clang: https://clang.llvm.org/docs/AddressSanitizer.html#conditional-compilation-with-has-feature-address-sanitizer
|
||||||
|
*/
|
||||||
|
#if defined(__SANITIZE_ADDRESS__)
|
||||||
|
#define ASN__SANITIZE_ENABLED 1
|
||||||
|
#elif defined(__has_feature)
|
||||||
|
#if __has_feature(address_sanitizer)
|
||||||
|
#define ASN__SANITIZE_ENABLED 1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#define ASN__DEFAULT_STACK_MAX (30000)
|
#define ASN__DEFAULT_STACK_MAX (30000)
|
||||||
#ifdef ASN_DISABLE_STACK_OVERFLOW_CHECK
|
|
||||||
|
#if defined(ASN__SANITIZE_ENABLED) || defined(ASN_DISABLE_STACK_OVERFLOW_CHECK)
|
||||||
static int CC_NOTUSED
|
static int CC_NOTUSED
|
||||||
ASN__STACK_OVERFLOW_CHECK(const asn_codec_ctx_t *ctx) {
|
ASN__STACK_OVERFLOW_CHECK(const asn_codec_ctx_t *ctx) {
|
||||||
(void)ctx;
|
(void)ctx;
|
||||||
|
|
|
@ -42,17 +42,22 @@ asn_random_between(intmax_t lb, intmax_t rb) {
|
||||||
uintmax_t range = asn__intmax_range(lb, rb);
|
uintmax_t range = asn__intmax_range(lb, rb);
|
||||||
uintmax_t value = 0;
|
uintmax_t value = 0;
|
||||||
uintmax_t got_entropy = 0;
|
uintmax_t got_entropy = 0;
|
||||||
|
|
||||||
(void)intmax_max;
|
(void)intmax_max;
|
||||||
assert(RAND_MAX > 0xffffff); /* Seen 7ffffffd! */
|
int max = 0xffffff;
|
||||||
|
|
||||||
|
#ifdef __WIN32__
|
||||||
|
max = RAND_MAX-1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
assert(RAND_MAX > max); /* Seen 7ffffffd! */
|
||||||
assert(range < intmax_max);
|
assert(range < intmax_max);
|
||||||
|
|
||||||
for(; got_entropy < range;) {
|
for(; got_entropy < range;) {
|
||||||
got_entropy = (got_entropy << 24) | 0xffffff;
|
got_entropy = (got_entropy << 24) | max;
|
||||||
#ifdef HAVE_RANDOM
|
#ifdef HAVE_RANDOM
|
||||||
value = (value << 24) | (random() % 0xffffff);
|
value = (value << 24) | (random() % max);
|
||||||
#else
|
#else
|
||||||
value = (value << 24) | (rand() % 0xffffff);
|
value = (value << 24) | (rand() % max);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,8 @@ CHOICE_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
|
||||||
value = per_get_few_bits(pd, 1);
|
value = per_get_few_bits(pd, 1);
|
||||||
if(value < 0) ASN__DECODE_STARVED;
|
if(value < 0) ASN__DECODE_STARVED;
|
||||||
if(value) ct = 0; /* Not restricted */
|
if(value) ct = 0; /* Not restricted */
|
||||||
|
if((unsigned)value >= td->elements_count)
|
||||||
|
ASN__DECODE_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ct && ct->range_bits >= 0) {
|
if(ct && ct->range_bits >= 0) {
|
||||||
|
@ -53,8 +55,8 @@ CHOICE_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
|
||||||
if(specs->ext_start == -1)
|
if(specs->ext_start == -1)
|
||||||
ASN__DECODE_FAILED;
|
ASN__DECODE_FAILED;
|
||||||
|
|
||||||
if (ct && ct->upper_bound >= ct->lower_bound) {
|
if(specs && specs->tag2el_count > specs->ext_start) {
|
||||||
value = aper_get_nsnnwn(pd, ct->upper_bound - ct->lower_bound + 1);
|
value = aper_get_nsnnwn(pd, specs->tag2el_count - specs->ext_start); /* extension elements range */
|
||||||
if(value < 0) ASN__DECODE_STARVED;
|
if(value < 0) ASN__DECODE_STARVED;
|
||||||
value += specs->ext_start;
|
value += specs->ext_start;
|
||||||
if((unsigned)value >= td->elements_count)
|
if((unsigned)value >= td->elements_count)
|
||||||
|
|
|
@ -1,10 +1,19 @@
|
||||||
Use mounse07410(vlm_master) git's fork for asn1c
|
Use mounse07410(vlm_master) git's fork for asn1c
|
||||||
|
|
||||||
commit ebed802c88b3049cfe67326e4df780cefc6da49e (HEAD -> vlm_master, origin/vlm_master, origin/HEAD)
|
commit 3e6592bd840b42a2e16cc6286449f286b118ae8b (HEAD, origin/vlm_master, origin/HEAD, vlm_master)
|
||||||
Author: Leith Bade <leith@swiftnav.com>
|
Merge: 29ef59bb 4e28be09
|
||||||
Date: Mon Nov 14 20:28:25 2022 +1100
|
Author: Mouse <mouse07410@users.noreply.github.com>
|
||||||
|
Date: Mon Nov 13 21:08:35 2023 -0500
|
||||||
|
|
||||||
Check SEQUENCE field constraint check result instead of returning
|
Merge pull request #140 from velichkov/mouse07410_issues134
|
||||||
|
|
||||||
|
commit 4e28be09549f3ad6ee4fd5e84996899671591a36
|
||||||
|
Author: Vasil Velichkov <vvvelichkov@gmail.com>
|
||||||
|
Date: Mon Nov 13 21:42:39 2023 +0200
|
||||||
|
|
||||||
|
aper: Check CHOICE present value is not greater than elements count
|
||||||
|
|
||||||
|
Fixes mouse07410/asn1c#134
|
||||||
|
|
||||||
===========================================
|
===========================================
|
||||||
user@host ~/Documents/git/my$ \
|
user@host ~/Documents/git/my$ \
|
||||||
|
|
|
@ -604,6 +604,55 @@ static void test6_func(abts_case *tc, void *data)
|
||||||
ogs_pkbuf_free(s1apbuf);
|
ogs_pkbuf_free(s1apbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test7_func(abts_case *tc, void *data)
|
||||||
|
{
|
||||||
|
const char *payload =
|
||||||
|
"0026406300000a00 7a400f2004d222a6 4500bf48f328170b b75b007a40020000"
|
||||||
|
"007a40020000007a 4004f5023d4d007a 50020000007a4003 00015a007a400b20"
|
||||||
|
"00008fc5f89e4556 4a667a0b400c2001 cc00acc4e7380083 bd93007a40030001"
|
||||||
|
"83007a40020000";
|
||||||
|
|
||||||
|
ogs_s1ap_message_t message;
|
||||||
|
ogs_pkbuf_t *enb_pkbuf;
|
||||||
|
int result;
|
||||||
|
char hexbuf[OGS_HUGE_LEN];
|
||||||
|
|
||||||
|
enb_pkbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN);
|
||||||
|
ogs_assert(enb_pkbuf);
|
||||||
|
ogs_pkbuf_put_data(enb_pkbuf,
|
||||||
|
ogs_hex_from_string(payload, hexbuf, sizeof(hexbuf)), 103);
|
||||||
|
|
||||||
|
result = ogs_s1ap_decode(&message, enb_pkbuf);
|
||||||
|
ABTS_INT_EQUAL(tc, -1, result);
|
||||||
|
|
||||||
|
ogs_s1ap_free(&message);
|
||||||
|
ogs_pkbuf_free(enb_pkbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test8_func(abts_case *tc, void *data)
|
||||||
|
{
|
||||||
|
const char *payload =
|
||||||
|
"0025405a00000a00 79400b2000001f64 1125bd6050210079 4002000000794006"
|
||||||
|
"0004680e99090079 4002000000794002 00000079400f2004 248c28ab0035cd56"
|
||||||
|
"ea3daf3f75007940 02000000794003ff 01f60079400200ea 007940020000";
|
||||||
|
|
||||||
|
ogs_s1ap_message_t message;
|
||||||
|
ogs_pkbuf_t *enb_pkbuf;
|
||||||
|
int result;
|
||||||
|
char hexbuf[OGS_HUGE_LEN];
|
||||||
|
|
||||||
|
enb_pkbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN);
|
||||||
|
ogs_assert(enb_pkbuf);
|
||||||
|
ogs_pkbuf_put_data(enb_pkbuf,
|
||||||
|
ogs_hex_from_string(payload, hexbuf, sizeof(hexbuf)), 94);
|
||||||
|
|
||||||
|
result = ogs_s1ap_decode(&message, enb_pkbuf);
|
||||||
|
ABTS_INT_EQUAL(tc, -1, result);
|
||||||
|
|
||||||
|
ogs_s1ap_free(&message);
|
||||||
|
ogs_pkbuf_free(enb_pkbuf);
|
||||||
|
}
|
||||||
|
|
||||||
abts_suite *test_crash(abts_suite *suite)
|
abts_suite *test_crash(abts_suite *suite)
|
||||||
{
|
{
|
||||||
suite = ADD_SUITE(suite)
|
suite = ADD_SUITE(suite)
|
||||||
|
@ -614,6 +663,8 @@ abts_suite *test_crash(abts_suite *suite)
|
||||||
abts_run_test(suite, test4_func, NULL);
|
abts_run_test(suite, test4_func, NULL);
|
||||||
abts_run_test(suite, test5_func, NULL);
|
abts_run_test(suite, test5_func, NULL);
|
||||||
abts_run_test(suite, test6_func, NULL);
|
abts_run_test(suite, test6_func, NULL);
|
||||||
|
abts_run_test(suite, test7_func, NULL);
|
||||||
|
abts_run_test(suite, test8_func, NULL);
|
||||||
|
|
||||||
return suite;
|
return suite;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue