improved INTEGER printing

git-svn-id: https://asn1c.svn.sourceforge.net/svnroot/asn1c/trunk@55 59561ff5-6e30-0410-9f3c-9617f08c8826
This commit is contained in:
vlm 2004-07-19 17:30:25 +00:00
parent f0769b419e
commit 7d278c491d
4 changed files with 61 additions and 7 deletions

View File

@ -3,6 +3,7 @@
* Fixed parser: memory leak in free_struct code for SET OF/SEQUENCE OF. * Fixed parser: memory leak in free_struct code for SET OF/SEQUENCE OF.
(Severity: high, Security impact: medium) (Severity: high, Security impact: medium)
* Improved INTEGER type printing.
0.8.14: 2004-Jun-30 0.8.14: 2004-Jun-30

View File

@ -186,8 +186,8 @@ INTEGER_encode_der(asn1_TYPE_descriptor_t *sd, void *ptr,
int int
INTEGER_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel, INTEGER_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel,
asn_app_consume_bytes_f *cb, void *app_key) { asn_app_consume_bytes_f *cb, void *app_key) {
char scratch[32]; /* Enough for 64-bit integer */
const INTEGER_t *st = sptr; const INTEGER_t *st = sptr;
char scratch[32];
uint8_t *buf = st->buf; uint8_t *buf = st->buf;
uint8_t *buf_end = st->buf + st->size; uint8_t *buf_end = st->buf + st->size;
signed long accum; signed long accum;
@ -202,9 +202,24 @@ INTEGER_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel,
if(st->size == 0) if(st->size == 0)
return cb("0", 1, app_key); return cb("0", 1, app_key);
/*
* Advance buf pointer until the start of the value's body.
* This will make us able to process large integers using simple case,
* when the actual value is small
* (0x0000000000abcdef would yield a fine 0x00abcdef)
*/
/* Skip the insignificant leading bytes */
for(; buf < buf_end-1; buf++) {
switch(*buf) {
case 0x00: if((buf[1] & 0x80) == 0) continue; break;
case 0xff: if((buf[1] & 0x80) != 0) continue; break;
}
break;
}
/* Simple case: the integer size is small */ /* Simple case: the integer size is small */
if((size_t)st->size < sizeof(accum) || (st->buf[0] & 0x80)) { if((size_t)(buf_end - buf) <= sizeof(accum)) {
accum = (st->buf[0] & 0x80) ? -1 : 0; accum = (*buf & 0x80) ? -1 : 0;
for(; buf < buf_end; buf++) for(; buf < buf_end; buf++)
accum = (accum << 8) | *buf; accum = (accum << 8) | *buf;
ret = snprintf(scratch, sizeof(scratch), "%ld", accum); ret = snprintf(scratch, sizeof(scratch), "%ld", accum);
@ -213,9 +228,10 @@ INTEGER_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel,
} }
/* Output in the long xx:yy:zz... format */ /* Output in the long xx:yy:zz... format */
/* TODO: replace with generic algorithm (Knuth TAOCP Vol 2, 4.3.1) */
for(p = scratch; buf < buf_end; buf++) { for(p = scratch; buf < buf_end; buf++) {
static char h2c[16] = "0123456789ABCDEF"; static char h2c[16] = "0123456789ABCDEF";
if((p - scratch) >= (ssize_t)(sizeof(scratch) / 2)) { if((p - scratch) >= (ssize_t)(sizeof(scratch) - 4)) {
/* Flush buffer */ /* Flush buffer */
if(cb(scratch, p - scratch, app_key)) if(cb(scratch, p - scratch, app_key))
return -1; return -1;
@ -225,6 +241,8 @@ INTEGER_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel,
*p++ = h2c[*buf & 0x0F]; *p++ = h2c[*buf & 0x0F];
*p++ = ':'; *p++ = ':';
} }
if(p != scratch)
p--; /* Remove the last ':' */
return cb(scratch, p - scratch, app_key); return cb(scratch, p - scratch, app_key);
} }

View File

@ -166,7 +166,7 @@ int
NativeInteger_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel, NativeInteger_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel,
asn_app_consume_bytes_f *cb, void *app_key) { asn_app_consume_bytes_f *cb, void *app_key) {
const int *Int = sptr; const int *Int = sptr;
char scratch[32]; char scratch[32]; /* Enough for 64-bit int */
int ret; int ret;
(void)td; /* Unused argument */ (void)td; /* Unused argument */

View File

@ -5,9 +5,22 @@
#include "../der_encoder.c" #include "../der_encoder.c"
#include "../constraints.c" #include "../constraints.c"
static char *shared_scratch_start;
static int _print2buf(const void *buf, size_t size, void *key) {
(void)key;
memcpy(shared_scratch_start, buf, size);
shared_scratch_start += size;
*shared_scratch_start = '\0'; /* 0-termination */
return 0;
}
static void static void
check(uint8_t *buf, int size, long check_long, int check_ret) { check(uint8_t *buf, int size, long check_long, int check_ret) {
char scratch[128];
char verify[32];
INTEGER_t val; INTEGER_t val;
uint8_t *buf_end = buf + size;
int ret; int ret;
long rlong = 123; long rlong = 123;
@ -17,13 +30,35 @@ check(uint8_t *buf, int size, long check_long, int check_ret) {
val.buf = buf; val.buf = buf;
val.size = size; val.size = size;
printf("Testing: [");
for(; buf < buf_end; buf++) {
if(buf != val.buf) printf(":");
printf("%02x", *buf);
}
printf("]: ");
ret = asn1_INTEGER2long(&val, &rlong); ret = asn1_INTEGER2long(&val, &rlong);
printf("Testing (%ld, %d) vs (%ld, %d)\n", printf(" (%ld, %d) vs (%ld, %d)\n",
rlong, ret, check_long, check_ret); rlong, ret, check_long, check_ret);
assert(ret == check_ret); assert(ret == check_ret);
if(ret == -1) return;
assert(rlong == check_long); assert(rlong == check_long);
shared_scratch_start = scratch;
ret = INTEGER_print(&asn1_DEF_INTEGER, &val, 0, _print2buf, scratch);
assert(shared_scratch_start < scratch + sizeof(scratch));
assert(ret == 0);
ret = snprintf(verify, sizeof(verify), "%ld", check_long);
assert(ret < sizeof(verify));
ret = strcmp(scratch, verify);
printf(" [%s] vs [%s]: %d%s\n",
scratch, verify, ret,
(check_ret == -1)?" (expected to fail)":""
);
if(check_ret == -1) {
assert(strcmp(scratch, verify));
} else {
assert(strcmp(scratch, verify) == 0);
}
} }
int int