aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLev Walkin <vlm@lionet.info>2012-02-15 10:03:11 -0800
committerLev Walkin <vlm@lionet.info>2012-02-15 10:03:11 -0800
commit94b765a1e013aa53e615a9d26a2338cf93870973 (patch)
treee2cc80904aad7cf0a4f8c786ac97d806cd993502
parentb89b340e049bc81abe5702bbd36faac5496a2566 (diff)
parent3d6fcfecd7aeff611ee3d16c5b2e1bc5187accee (diff)
Merge branch 'master' of github.com:vlm/asn1c
-rw-r--r--.gitignore1
-rw-r--r--libasn1compiler/asn1c_constraint.c23
-rw-r--r--skeletons/GeneralizedTime.c6
-rw-r--r--skeletons/INTEGER.c11
-rw-r--r--skeletons/OBJECT_IDENTIFIER.c3
-rw-r--r--skeletons/tests/check-INTEGER.c35
-rw-r--r--skeletons/tests/check-OIDs.c5
7 files changed, 64 insertions, 20 deletions
diff --git a/.gitignore b/.gitignore
index 8c79b742..8b52d471 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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);