diff --git a/lib/asn1c/common/BIT_STRING_jer.c b/lib/asn1c/common/BIT_STRING_jer.c index 69c320d2f..f66238dee 100644 --- a/lib/asn1c/common/BIT_STRING_jer.c +++ b/lib/asn1c/common/BIT_STRING_jer.c @@ -6,21 +6,15 @@ #include #include -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 BIT_STRING_encode_jer(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, enum jer_encoder_flags_e flags, asn_app_consume_bytes_f *cb, void *app_key) { 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 *scend = scratch + (sizeof(scratch) - 10); const BIT_STRING_t *st = (const BIT_STRING_t *)sptr; - int xcan = 0; uint8_t *buf; 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 */ /* - * Binary dump + * Hex dump */ - for(; buf < end; buf++) { - int v = *buf; - int nline = xcan?0:(((buf - st->buf) % 8) == 0); - if(p >= scend || nline) { - ASN__CALLBACK(scratch, p - scratch); + *p++ = '"'; + for(int i = 0; buf < end; buf++, i++) { + if(!(i % 16) && (i || st->size > 16)) { + ASN__CALLBACK(scratch, p-scratch); p = scratch; - if(nline) ASN__TEXT_INDENT(1, ilevel); } - memcpy(p + 0, _bit_pattern[v >> 4], 4); - memcpy(p + 4, _bit_pattern[v & 0x0f], 4); - p += 8; + *p++ = h2c[*buf >> 4]; + *p++ = h2c[*buf & 0x0F]; } - if(!xcan && ((buf - st->buf) % 8) == 0) - ASN__TEXT_INDENT(1, ilevel); ASN__CALLBACK(scratch, p - scratch); p = scratch; if(buf == end) { - int v = *buf; int ubits = st->bits_unused; - int i; - for(i = 7; i >= ubits; i--) - *p++ = (v & (1 << i)) ? 0x31 : 0x30; + uint8_t v = *buf & (0xff << ubits); + *p++ = h2c[v >> 4]; + *p++ = h2c[v & 0x0F]; ASN__CALLBACK(scratch, p - scratch); + p = scratch; } - - if(!xcan) ASN__TEXT_INDENT(1, ilevel - 1); + *p++ = '"'; + ASN__CALLBACK(scratch, p - scratch); + ASN__TEXT_INDENT(1, ilevel - 1); ASN__ENCODED_OK(er); cb_failed: diff --git a/lib/asn1c/common/OCTET_STRING_jer.c b/lib/asn1c/common/OCTET_STRING_jer.c index 19b4fc314..d744cc3e3 100644 --- a/lib/asn1c/common/OCTET_STRING_jer.c +++ b/lib/asn1c/common/OCTET_STRING_jer.c @@ -30,22 +30,19 @@ OCTET_STRING_encode_jer(const asn_TYPE_descriptor_t *td, const void *sptr, */ buf = st->buf; end = buf + st->size; + ASN__CALLBACK("\"", 1); for(i = 0; buf < end; buf++, i++) { if(!(i % 16) && (i || st->size > 16)) { ASN__CALLBACK(scratch, p-scratch); p = scratch; - ASN__TEXT_INDENT(1, ilevel); } *p++ = h2c[(*buf >> 4) & 0x0F]; *p++ = h2c[*buf & 0x0F]; - *p++ = 0x20; } if(p - scratch) { - p--; /* Remove the tail space */ - ASN__CALLBACK3("\"", 1, scratch, p-scratch, "\"", 1); /* Dump the rest */ - if(st->size > 16) - ASN__TEXT_INDENT(1, ilevel-1); + ASN__CALLBACK(scratch, p-scratch); /* Dump the rest */ } + ASN__CALLBACK("\"", 1); ASN__ENCODED_OK(er); cb_failed: diff --git a/lib/asn1c/common/asn_internal.h b/lib/asn1c/common/asn_internal.h index 6fc5478ab..af619af14 100644 --- a/lib/asn1c/common/asn_internal.h +++ b/lib/asn1c/common/asn_internal.h @@ -179,8 +179,25 @@ asn__format_to_callback( /* * 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) -#ifdef ASN_DISABLE_STACK_OVERFLOW_CHECK + +#if defined(ASN__SANITIZE_ENABLED) || defined(ASN_DISABLE_STACK_OVERFLOW_CHECK) static int CC_NOTUSED ASN__STACK_OVERFLOW_CHECK(const asn_codec_ctx_t *ctx) { (void)ctx; diff --git a/lib/asn1c/common/asn_random_fill.c b/lib/asn1c/common/asn_random_fill.c index 29653623a..15771b6c7 100644 --- a/lib/asn1c/common/asn_random_fill.c +++ b/lib/asn1c/common/asn_random_fill.c @@ -42,17 +42,22 @@ asn_random_between(intmax_t lb, intmax_t rb) { uintmax_t range = asn__intmax_range(lb, rb); uintmax_t value = 0; uintmax_t got_entropy = 0; - (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); for(; got_entropy < range;) { - got_entropy = (got_entropy << 24) | 0xffffff; + got_entropy = (got_entropy << 24) | max; #ifdef HAVE_RANDOM - value = (value << 24) | (random() % 0xffffff); + value = (value << 24) | (random() % max); #else - value = (value << 24) | (rand() % 0xffffff); + value = (value << 24) | (rand() % max); #endif } diff --git a/lib/asn1c/common/constr_CHOICE_aper.c b/lib/asn1c/common/constr_CHOICE_aper.c index 88daaf2c0..0d356f7f9 100644 --- a/lib/asn1c/common/constr_CHOICE_aper.c +++ b/lib/asn1c/common/constr_CHOICE_aper.c @@ -40,6 +40,8 @@ CHOICE_decode_aper(const asn_codec_ctx_t *opt_codec_ctx, value = per_get_few_bits(pd, 1); if(value < 0) ASN__DECODE_STARVED; if(value) ct = 0; /* Not restricted */ + if((unsigned)value >= td->elements_count) + ASN__DECODE_FAILED; } 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) ASN__DECODE_FAILED; - if (ct && ct->upper_bound >= ct->lower_bound) { - value = aper_get_nsnnwn(pd, ct->upper_bound - ct->lower_bound + 1); + if(specs && specs->tag2el_count > specs->ext_start) { + value = aper_get_nsnnwn(pd, specs->tag2el_count - specs->ext_start); /* extension elements range */ if(value < 0) ASN__DECODE_STARVED; value += specs->ext_start; if((unsigned)value >= td->elements_count) diff --git a/lib/asn1c/support/README.md b/lib/asn1c/support/README.md index 820984841..7ccaa4cbe 100644 --- a/lib/asn1c/support/README.md +++ b/lib/asn1c/support/README.md @@ -1,10 +1,19 @@ Use mounse07410(vlm_master) git's fork for asn1c -commit ebed802c88b3049cfe67326e4df780cefc6da49e (HEAD -> vlm_master, origin/vlm_master, origin/HEAD) -Author: Leith Bade -Date: Mon Nov 14 20:28:25 2022 +1100 +commit 3e6592bd840b42a2e16cc6286449f286b118ae8b (HEAD, origin/vlm_master, origin/HEAD, vlm_master) +Merge: 29ef59bb 4e28be09 +Author: Mouse +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 +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$ \ diff --git a/tests/unit/crash-test.c b/tests/unit/crash-test.c index 7cd13c4f2..de4799b4a 100644 --- a/tests/unit/crash-test.c +++ b/tests/unit/crash-test.c @@ -604,6 +604,55 @@ static void test6_func(abts_case *tc, void *data) 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) { 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, test5_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; }