aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLev Walkin <vlm@lionet.info>2004-07-19 17:30:25 +0000
committerLev Walkin <vlm@lionet.info>2004-07-19 17:30:25 +0000
commitdb13f518da492076d0f7ac10459640baec0b5f5f (patch)
tree02d0cb05b30ba68b3585153d402fdbab89504423
parent29a62261e1698d54bf7bcf8ea2c60f336241c3af (diff)
improved INTEGER printing
-rw-r--r--ChangeLog1
-rw-r--r--skeletons/INTEGER.c26
-rw-r--r--skeletons/NativeInteger.c2
-rw-r--r--skeletons/tests/check-INTEGER.c39
4 files changed, 61 insertions, 7 deletions
diff --git a/ChangeLog b/ChangeLog
index fbb2510e..cb6b9d4b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/skeletons/INTEGER.c b/skeletons/INTEGER.c
index d20379fb..120b94fe 100644
--- a/skeletons/INTEGER.c
+++ b/skeletons/INTEGER.c
@@ -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);
}
diff --git a/skeletons/NativeInteger.c b/skeletons/NativeInteger.c
index 8203695c..8f13a591 100644
--- a/skeletons/NativeInteger.c
+++ b/skeletons/NativeInteger.c
@@ -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 */
diff --git a/skeletons/tests/check-INTEGER.c b/skeletons/tests/check-INTEGER.c
index 4053075e..5aa400d5 100644
--- a/skeletons/tests/check-INTEGER.c
+++ b/skeletons/tests/check-INTEGER.c
@@ -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