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.
(Severity: high, Security impact: medium)
* Improved INTEGER type printing.
0.8.14: 2004-Jun-30

View File

@ -186,8 +186,8 @@ INTEGER_encode_der(asn1_TYPE_descriptor_t *sd, void *ptr,
int
INTEGER_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel,
asn_app_consume_bytes_f *cb, void *app_key) {
char scratch[32]; /* Enough for 64-bit integer */
const INTEGER_t *st = sptr;
char scratch[32];
uint8_t *buf = st->buf;
uint8_t *buf_end = st->buf + st->size;
signed long accum;
@ -202,9 +202,24 @@ INTEGER_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel,
if(st->size == 0)
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 */
if((size_t)st->size < sizeof(accum) || (st->buf[0] & 0x80)) {
accum = (st->buf[0] & 0x80) ? -1 : 0;
if((size_t)(buf_end - buf) <= sizeof(accum)) {
accum = (*buf & 0x80) ? -1 : 0;
for(; buf < buf_end; buf++)
accum = (accum << 8) | *buf;
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 */
/* TODO: replace with generic algorithm (Knuth TAOCP Vol 2, 4.3.1) */
for(p = scratch; buf < buf_end; buf++) {
static char h2c[16] = "0123456789ABCDEF";
if((p - scratch) >= (ssize_t)(sizeof(scratch) / 2)) {
if((p - scratch) >= (ssize_t)(sizeof(scratch) - 4)) {
/* Flush buffer */
if(cb(scratch, p - scratch, app_key))
return -1;
@ -225,6 +241,8 @@ INTEGER_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel,
*p++ = h2c[*buf & 0x0F];
*p++ = ':';
}
if(p != scratch)
p--; /* Remove the last ':' */
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,
asn_app_consume_bytes_f *cb, void *app_key) {
const int *Int = sptr;
char scratch[32];
char scratch[32]; /* Enough for 64-bit int */
int ret;
(void)td; /* Unused argument */

View File

@ -5,9 +5,22 @@
#include "../der_encoder.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
check(uint8_t *buf, int size, long check_long, int check_ret) {
char scratch[128];
char verify[32];
INTEGER_t val;
uint8_t *buf_end = buf + size;
int ret;
long rlong = 123;
@ -17,13 +30,35 @@ check(uint8_t *buf, int size, long check_long, int check_ret) {
val.buf = buf;
val.size = size;
printf("Testing: [");
for(; buf < buf_end; buf++) {
if(buf != val.buf) printf(":");
printf("%02x", *buf);
}
printf("]: ");
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);
assert(ret == check_ret);
if(ret == -1) return;
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