Commit 0be3a998 authored by Lev Walkin's avatar Lev Walkin
Browse files

INTEGER XER decoding

parent 2ffc01d3
......@@ -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
......
......@@ -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.
*/
......
......@@ -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;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment