diff options
author | Lev Walkin <vlm@lionet.info> | 2012-02-15 10:03:11 -0800 |
---|---|---|
committer | Lev Walkin <vlm@lionet.info> | 2012-02-15 10:03:11 -0800 |
commit | 94b765a1e013aa53e615a9d26a2338cf93870973 (patch) | |
tree | e2cc80904aad7cf0a4f8c786ac97d806cd993502 | |
parent | b89b340e049bc81abe5702bbd36faac5496a2566 (diff) | |
parent | 3d6fcfecd7aeff611ee3d16c5b2e1bc5187accee (diff) |
Merge branch 'master' of github.com:vlm/asn1c
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | libasn1compiler/asn1c_constraint.c | 23 | ||||
-rw-r--r-- | skeletons/GeneralizedTime.c | 6 | ||||
-rw-r--r-- | skeletons/INTEGER.c | 11 | ||||
-rw-r--r-- | skeletons/OBJECT_IDENTIFIER.c | 3 | ||||
-rw-r--r-- | skeletons/tests/check-INTEGER.c | 35 | ||||
-rw-r--r-- | skeletons/tests/check-OIDs.c | 5 |
7 files changed, 64 insertions, 20 deletions
@@ -3,6 +3,7 @@ *.lo *.libs *.deps +*.core # / /autom4te.cache diff --git a/libasn1compiler/asn1c_constraint.c b/libasn1compiler/asn1c_constraint.c index 2b1420e8..e9d796de 100644 --- a/libasn1compiler/asn1c_constraint.c +++ b/libasn1compiler/asn1c_constraint.c @@ -14,6 +14,16 @@ static asn1p_expr_type_e _find_terminal_type(arg_t *arg); static int emit_range_comparison_code(arg_t *arg, asn1cnst_range_t *range, const char *varname, asn1c_integer_t natural_start, asn1c_integer_t natural_stop); static int native_long_sign(asn1cnst_range_t *r); /* -1, 0, 1 */ +static int +ulong_optimization(asn1p_expr_type_e etype, asn1cnst_range_t *r_size, + asn1cnst_range_t *r_value) +{ + return (!r_size && r_value + && (etype == ASN_BASIC_INTEGER + || etype == ASN_BASIC_ENUMERATED) + && native_long_sign(r_value) == 0); +} + int asn1c_emit_constraint_checking_code(arg_t *arg) { asn1cnst_range_t *r_size; @@ -24,6 +34,7 @@ asn1c_emit_constraint_checking_code(arg_t *arg) { int got_something = 0; int alphabet_table_compiled; int produce_st = 0; + int ulong_optimize = 0; ct = expr->combined_constraints; if(ct == NULL) @@ -93,7 +104,10 @@ asn1c_emit_constraint_checking_code(arg_t *arg) { case ASN_BASIC_INTEGER: case ASN_BASIC_ENUMERATED: if(native_long_sign(r_value) >= 0) { - OUT("unsigned long value;\n"); + ulong_optimize = ulong_optimization(etype, r_size, r_value); + if(!ulong_optimize) { + OUT("unsigned long value;\n"); + } } else { OUT("long value;\n"); } @@ -124,7 +138,7 @@ asn1c_emit_constraint_checking_code(arg_t *arg) { OUT("}\n"); OUT("\n"); - if(r_value) + if((r_value) && (!ulong_optimize)) emit_value_determination_code(arg, etype, r_value); if(r_size) emit_size_determination_code(arg, etype); @@ -140,10 +154,7 @@ asn1c_emit_constraint_checking_code(arg_t *arg) { /* * Optimization for unsigned longs. */ - if(!r_size && r_value - && (etype == ASN_BASIC_INTEGER - || etype == ASN_BASIC_ENUMERATED) - && native_long_sign(r_value) == 0) { + if(ulong_optimize) { OUT("\n"); OUT("/* Constraint check succeeded */\n"); OUT("return 0;\n"); diff --git a/skeletons/GeneralizedTime.c b/skeletons/GeneralizedTime.c index 1a16ba8a..7794bd43 100644 --- a/skeletons/GeneralizedTime.c +++ b/skeletons/GeneralizedTime.c @@ -314,7 +314,8 @@ asn_GT2time_prec(const GeneralizedTime_t *st, int *frac_value, int frac_digits, while(fd > frac_digits) fv /= 10, fd--; while(fd < frac_digits) { - int new_fv = fv * 10; + int volatile new_fv = fv * 10; + /* GCC 4.x is being too smart without volatile */ if(new_fv / 10 != fv) { /* Too long precision request */ fv = 0; @@ -441,7 +442,8 @@ asn_GT2time_frac(const GeneralizedTime_t *st, int *frac_value, int *frac_digits, */ for(buf++; buf < end; buf++) { int v = *buf; - int new_fvalue; + int volatile new_fvalue; + /* GCC 4.x is being too smart without volatile */ switch(v) { case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: diff --git a/skeletons/INTEGER.c b/skeletons/INTEGER.c index 5b103159..c6e1d910 100644 --- a/skeletons/INTEGER.c +++ b/skeletons/INTEGER.c @@ -339,6 +339,9 @@ INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chun ASN_DEBUG("INTEGER body %ld 0x%2x..0x%2x", (long)chunk_size, *lstart, lstop[-1]); + if(INTEGER_st_prealloc(st, (chunk_size/3) + 1)) + return XPBD_SYSTEM_FAILURE; + /* * We may have received a tag here. It will be processed inline. * Use strtoul()-like code and serialize the result. @@ -396,7 +399,9 @@ INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chun } { - long new_value = value * 10; + long volatile new_value = value * 10; + /* GCC 4.x optimizes (new_value) without `volatile' + * so the following check does not detect overflow. */ if(new_value / 10 != value) /* Overflow */ @@ -445,8 +450,6 @@ INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chun * places as a decimal value. * Switch decoding mode. */ ASN_DEBUG("INTEGER re-evaluate as hex form"); - if(INTEGER_st_prealloc(st, (chunk_size/3) + 1)) - return XPBD_SYSTEM_FAILURE; state = ST_SKIPSPHEX; lp = lstart - 1; continue; @@ -474,8 +477,6 @@ INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chun continue; case ST_DIGITS: ASN_DEBUG("INTEGER re-evaluate as hex form"); - if(INTEGER_st_prealloc(st, (chunk_size/3) + 1)) - return XPBD_SYSTEM_FAILURE; state = ST_SKIPSPHEX; lp = lstart - 1; continue; diff --git a/skeletons/OBJECT_IDENTIFIER.c b/skeletons/OBJECT_IDENTIFIER.c index 0d7043e6..ed083f8a 100644 --- a/skeletons/OBJECT_IDENTIFIER.c +++ b/skeletons/OBJECT_IDENTIFIER.c @@ -691,7 +691,8 @@ OBJECT_IDENTIFIER_parse_arcs(const char *oid_text, ssize_t oid_txt_length, value = 0; } if(1) { - long new_value = value * 10; + long volatile new_value = value * 10; + /* GCC 4.x is being too smart without volatile */ if(new_value / 10 != value || (value = new_value + (*oid_text - 0x30)) < 0) { /* Overflow */ diff --git a/skeletons/tests/check-INTEGER.c b/skeletons/tests/check-INTEGER.c index a299fcd5..b4b8e675 100644 --- a/skeletons/tests/check-INTEGER.c +++ b/skeletons/tests/check-INTEGER.c @@ -100,7 +100,6 @@ check_unsigned(uint8_t *buf, int size, unsigned long check_long, int check_ret) printf(" (%lu, %d) vs (%lu, %d)\n", rlong, ret, check_long, check_ret); assert(ret == check_ret); - printf("%lu %lu\n", rlong, check_long); assert(rlong == check_long); if(check_ret == 0) { @@ -122,13 +121,13 @@ check_unsigned(uint8_t *buf, int size, unsigned long check_long, int check_ret) assert(rlong == rlong2); } - return 0; + return; shared_scratch_start = scratch; ret = INTEGER_print(&asn_DEF_INTEGER, &val, 0, _print2buf, scratch); assert(shared_scratch_start < scratch + sizeof(scratch)); assert(ret == 0); - ret = snprintf(verify, sizeof(verify), "%ld", check_long); + ret = snprintf(verify, sizeof(verify), "%lu", check_long); assert(ret < sizeof(verify)); ret = strcmp(scratch, verify); printf(" [%s] vs [%s]: %d%s\n", @@ -208,8 +207,8 @@ main(int ac, char **av) { CHECK(buf12, -32768, 0); CHECK(buf13, -128, 0); UCHECK(buf14, 0x800000, 0); - UCHECK(buf15, 0x80000000, 0); - UCHECK(buf16, 0xffff0000, 0); + UCHECK(buf15, 0x80000000UL, 0); + UCHECK(buf16, 0xffff0000UL, 0); check_xer(-1, "", 0); check_xer(-1, "<INTEGER></INTEGER>", 0); @@ -240,6 +239,8 @@ main(int ac, char **av) { check_xer(0, "<INTEGER>+2147483647</INTEGER>", 2147483647); check_xer(0, "<INTEGER>2147483647</INTEGER>", 2147483647); if(sizeof(long) == 4) { + check_xer( 0, "<INTEGER>-2147483648</INTEGER>", -2147483648); + check_xer(-1, "<INTEGER>-2147483649</INTEGER>", 0); check_xer(-1, "<INTEGER>2147483648</INTEGER>", 0); check_xer(-1, "<INTEGER>2147483649</INTEGER>", 0); check_xer(-1, "<INTEGER>3147483649</INTEGER>", 0); @@ -247,6 +248,30 @@ main(int ac, char **av) { check_xer(-1, "<INTEGER>5147483649</INTEGER>", 0); /* special */ check_xer(-1, "<INTEGER>9147483649</INTEGER>", 0); check_xer(-1, "<INTEGER>9999999999</INTEGER>", 0); + check_xer(-1, "<INTEGER>-5147483649</INTEGER>", 0);/* special */ + check_xer(-1, "<INTEGER>-9147483649</INTEGER>", 0); + check_xer(-1, "<INTEGER>-9999999999</INTEGER>", 0); + } + if(sizeof(long) == 8) { + check_xer(0, "<INTEGER>2147483648</INTEGER>", 2147483648); + check_xer(0, "<INTEGER>2147483649</INTEGER>", 2147483649); + check_xer(0, "<INTEGER>3147483649</INTEGER>", 3147483649); + check_xer(0, "<INTEGER>4147483649</INTEGER>", 4147483649); + check_xer(0, "<INTEGER>5147483649</INTEGER>", 5147483649); + check_xer(0, "<INTEGER>9147483649</INTEGER>", 9147483649); + check_xer(0, "<INTEGER>9999999999</INTEGER>", 9999999999); + check_xer(0, "<INTEGER>9223372036854775807</INTEGER>", 9223372036854775807); + check_xer(-1, "<INTEGER>9223372036854775808</INTEGER>", 0); + check_xer(-1, "<INTEGER>10223372036854775807</INTEGER>", 0); + check_xer(-1, "<INTEGER>50223372036854775807</INTEGER>", 0); + check_xer(-1, "<INTEGER>100223372036854775807</INTEGER>", 0); + check_xer(-1, "<INTEGER>500223372036854775807</INTEGER>", 0); + check_xer(0, "<INTEGER>-9223372036854775808</INTEGER>", -9223372036854775808); + check_xer(-1, "<INTEGER>-9223372036854775809</INTEGER>", 0); + check_xer(-1, "<INTEGER>-10223372036854775807</INTEGER>", 0); + check_xer(-1, "<INTEGER>-50223372036854775807</INTEGER>", 0); + check_xer(-1, "<INTEGER>-100223372036854775807</INTEGER>", 0); + check_xer(-1, "<INTEGER>-500223372036854775807</INTEGER>", 0); } return 0; diff --git a/skeletons/tests/check-OIDs.c b/skeletons/tests/check-OIDs.c index 7609ed12..0805baac 100644 --- a/skeletons/tests/check-OIDs.c +++ b/skeletons/tests/check-OIDs.c @@ -400,13 +400,16 @@ main() { check_parse("1.2147483647.3", 3); if(sizeof(long) == 4) { check_parse("1.2147483648.3", -1); /* overflow on ILP32 */ + check_parse("1.2147483649.3", -1); /* overflow on ILP32 */ check_parse("1.3000000000.3", -1); check_parse("1.4000000000.3", -1); check_parse("1.5000000000.3", -1); check_parse("1.6000000000.3", -1); check_parse("1.9000000000.3", -1); - } else { + } else if(sizeof(long) == 8) { check_parse("1.2147483648.3", 3); + check_parse("1.9223372036854775807.3", 3); + check_parse("1.9223372036854775808.3", -1); } check_parse("1.900a0000000.3", -1); check_parse("1.900a.3", -1); |