mirror of https://gerrit.osmocom.org/asn1c
INTEGER XER decoding
git-svn-id: https://asn1c.svn.sourceforge.net/svnroot/asn1c/trunk@525 59561ff5-6e30-0410-9f3c-9617f08c8826
This commit is contained in:
parent
e3e88c743c
commit
e4f9cac8e2
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue