From 0be3a99877a563387b6384cdc5272d1040517901 Mon Sep 17 00:00:00 2001 From: Lev Walkin <vlm@lionet.info> Date: Thu, 21 Oct 2004 12:11:57 +0000 Subject: [PATCH] INTEGER XER decoding --- skeletons/INTEGER.c | 21 ++++++++--- skeletons/asn_codecs_prim.c | 28 +++++++++++++++ skeletons/tests/check-INTEGER.c | 63 +++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+), 5 deletions(-) diff --git a/skeletons/INTEGER.c b/skeletons/INTEGER.c index c4fb9721..1037bdd4 100644 --- a/skeletons/INTEGER.c +++ b/skeletons/INTEGER.c @@ -183,6 +183,7 @@ static ssize_t INTEGER__xer_body_decode(INTEGER_t *st, void *chunk_buf, size_t chunk_size) { long sign = 1; long value; + char *lp; char *lstart = (char *)chunk_buf; char *lstop = chunk_buf + chunk_size; enum { @@ -190,12 +191,13 @@ INTEGER__xer_body_decode(INTEGER_t *st, void *chunk_buf, size_t chunk_size) { ST_WAITDIGITS, ST_DIGITS, } state = ST_SKIPSPACE; + /* * We may receive a tag here. But we aren't ready to deal with it yet. * So, just use stroul()-like code and serialize the result. */ - for(value = 0; lstart < lstop; lstart++) { - int lv = *lstart; + for(value = 0, lp = lstart; lp < lstop; lp++) { + int lv = *lp; switch(lv) { case 0x09: case 0x0a: case 0x0d: case 0x20: if(state == ST_SKIPSPACE) continue; @@ -217,20 +219,29 @@ INTEGER__xer_body_decode(INTEGER_t *st, void *chunk_buf, size_t chunk_size) { case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: if(state != ST_DIGITS) state = ST_DIGITS; - value = value * 10 + (lv - 0x30); + { + long new_value = value * 10; + + if(new_value / 10 != value) + /* Overflow */ + return -1; + + value = new_value + (lv - 0x30); /* Check for two's complement overflow */ if(value < 0) { /* Check whether it is a LONG_MIN */ if(sign == -1 && value == ~((unsigned long)-1 >> 1)) { - sign = 0; + sign = 1; } else { /* Overflow */ return -1; } } + } continue; } + break; } if(state != ST_DIGITS) @@ -241,7 +252,7 @@ INTEGER__xer_body_decode(INTEGER_t *st, void *chunk_buf, size_t chunk_size) { if(asn_long2INTEGER(st, value)) return -1; - return lstop - lstart; + return lp - lstart; } asn_dec_rval_t diff --git a/skeletons/asn_codecs_prim.c b/skeletons/asn_codecs_prim.c index e0b545a5..87914756 100644 --- a/skeletons/asn_codecs_prim.c +++ b/skeletons/asn_codecs_prim.c @@ -143,12 +143,38 @@ struct xdp_arg_s { int want_more; }; +/* + * Check whether this buffer consists of entirely XER whitespace characters. + */ +static int +xer_decode__check_whitespace(void *chunk_buf, size_t chunk_size) { + char *p = (char *)chunk_buf; + char *pend = p + chunk_size; + for(; p < pend; p++) { + switch(*p) { + /* X.693, #8.1.4 + * HORISONTAL TAB (9) + * LINE FEED (10) + * CARRIAGE RETURN (13) + * SPACE (32) + */ + case 0x09: case 0x0a: case 0x0d: case 0x20: + break; + default: + return 0; + } + } + return 1; /* All whitespace */ +} + static int xer_decode__unexpected_tag(void *key, void *chunk_buf, size_t chunk_size) { struct xdp_arg_s *arg = (struct xdp_arg_s *)key; ssize_t decoded; if(arg->decoded_something) { + if(xer_decode__check_whitespace(chunk_buf, chunk_size)) + return chunk_size; /* * Decoding was done once already. Prohibit doing it again. */ @@ -171,6 +197,8 @@ xer_decode__body(void *key, void *chunk_buf, size_t chunk_size, int have_more) { ssize_t decoded; if(arg->decoded_something) { + if(xer_decode__check_whitespace(chunk_buf, chunk_size)) + return chunk_size; /* * Decoding was done once already. Prohibit doing it again. */ diff --git a/skeletons/tests/check-INTEGER.c b/skeletons/tests/check-INTEGER.c index ea686b43..81aae6e5 100644 --- a/skeletons/tests/check-INTEGER.c +++ b/skeletons/tests/check-INTEGER.c @@ -78,6 +78,34 @@ check(uint8_t *buf, int size, long check_long, int check_ret) { } } +static void +check_xer(int tofail, char *xmldata, long orig_value) { + INTEGER_t *st = 0; + asn_dec_rval_t rc; + long value; + int ret; + + printf("[%s] vs %ld:\n", xmldata, orig_value); + + rc = xer_decode(0, &asn_DEF_INTEGER, (void *)&st, + xmldata, strlen(xmldata)); + if(rc.code != RC_OK) { + assert(tofail); + printf("\tfailed, as expected\n"); + return; + } + assert(!tofail); + + ret = asn_INTEGER2long(st, &value); + assert(ret == 0); + + printf("\t%ld\n", value); + + assert(value == orig_value); + + asn_DEF_INTEGER.free_struct(&asn_DEF_INTEGER, st, 0); +} + int main(int ac, char **av) { uint8_t buf1[] = { 1 }; @@ -110,5 +138,40 @@ main(int ac, char **av) { CHECK(buf12, -32768, 0); CHECK(buf13, -128, 0); + check_xer(-1, "", 0); + check_xer(-1, "<INTEGER></INTEGER>", 0); + check_xer(-1, "<INTEGER>-</INTEGER>", 0); + check_xer(-1, "<INTEGER>+</INTEGER>", 0); + check_xer(-1, "<INTEGER>+-</INTEGER>", 0); + check_xer(0, "<INTEGER>+0</INTEGER>", 0); + check_xer(0, "<INTEGER>-0</INTEGER>", 0); + check_xer(0, "<INTEGER>+1</INTEGER>", 1); + check_xer(0, "<INTEGER>-1</INTEGER>", -1); + check_xer(0, "<INTEGER>1</INTEGER>", 1); + check_xer(0, "<INTEGER>-15</INTEGER>", -15); + check_xer(0, "<INTEGER>+15</INTEGER>", 15); + check_xer(0, "<INTEGER>15</INTEGER>", 15); + check_xer(0, "<INTEGER> 15</INTEGER>", 15); + check_xer(0, "<INTEGER> 15 </INTEGER>", 15); + check_xer(0, "<INTEGER>15 </INTEGER>", 15); + check_xer(0, "<INTEGER> +15 </INTEGER>", 15); + check_xer(-1, "<INTEGER> +15 -</INTEGER>", 0); + check_xer(-1, "<INTEGER> +15 1</INTEGER>", 0); + check_xer(-1, "<INTEGER>+ 15</INTEGER>", 0); + check_xer(-1, "<INTEGER>12<z>34</INTEGER>", 0); + check_xer(0, "<INTEGER>1234</INTEGER>", 1234); + check_xer(-1, "<INTEGER>1234 5678</INTEGER>", 0); + check_xer(0, "<INTEGER>-2147483647</INTEGER>", -2147483647); + check_xer(0, "<INTEGER>-2147483648</INTEGER>", -2147483648); + check_xer(0, "<INTEGER>+2147483647</INTEGER>", 2147483647); + check_xer(0, "<INTEGER>2147483647</INTEGER>", 2147483647); + check_xer(-1, "<INTEGER>2147483648</INTEGER>", 0); + check_xer(-1, "<INTEGER>2147483649</INTEGER>", 0); + check_xer(-1, "<INTEGER>3147483649</INTEGER>", 0); + check_xer(-1, "<INTEGER>4147483649</INTEGER>", 0); + check_xer(-1, "<INTEGER>5147483649</INTEGER>", 0); /* unobvious */ + check_xer(-1, "<INTEGER>9147483649</INTEGER>", 0); + check_xer(-1, "<INTEGER>9999999999</INTEGER>", 0); + return 0; } -- GitLab