From b75023664b529d1cd0dccac2deae78ddbd681369 Mon Sep 17 00:00:00 2001 From: Adam Dickmeiss Date: Tue, 11 Mar 2003 11:03:30 +0000 Subject: [PATCH] Fixes for random/hostile BER. --- include/yaz/odr.h | 8 +++++--- odr/ber_any.c | 13 ++++++------- odr/ber_bit.c | 17 +++++++++++------ odr/ber_bool.c | 14 +++++++------- odr/ber_int.c | 28 ++++++++++++---------------- odr/ber_len.c | 12 +++++++++--- odr/ber_null.c | 11 ++++++++--- odr/ber_oct.c | 15 ++++++++++----- odr/ber_oid.c | 22 ++++++++++++++-------- odr/ber_tag.c | 39 ++++++++++++++++++++++----------------- odr/dumpber.c | 38 ++++++++++++++++++++++++-------------- odr/odr-priv.h | 6 +++++- odr/odr.c | 18 ++++++++++++++++-- odr/odr_any.c | 4 ++-- odr/odr_choice.c | 4 ++-- odr/odr_cons.c | 35 +++++++++++++++++++++++++---------- odr/odr_enum.c | 4 ++-- odr/odr_int.c | 4 ++-- odr/odr_mem.c | 6 +++--- odr/odr_null.c | 4 ++-- odr/odr_oct.c | 8 ++++---- odr/odr_oid.c | 4 ++-- odr/odr_seq.c | 4 ++-- odr/odr_tag.c | 8 ++++---- 24 files changed, 199 insertions(+), 127 deletions(-) diff --git a/include/yaz/odr.h b/include/yaz/odr.h index a95d9e1..b9bd91f 100644 --- a/include/yaz/odr.h +++ b/include/yaz/odr.h @@ -23,7 +23,7 @@ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. * - * $Id: odr.h,v 1.8 2003-02-12 15:06:43 adam Exp $ + * $Id: odr.h,v 1.9 2003-03-11 11:03:30 adam Exp $ */ #ifndef ODR_H @@ -183,6 +183,8 @@ typedef struct odr_arm extern char *odr_errlist[]; YAZ_EXPORT int odr_geterror(ODR o); +YAZ_EXPORT int odr_geterrorx(ODR o, int *x); +YAZ_EXPORT void odr_seterror(ODR o, int errorno, int errorid); YAZ_EXPORT void odr_perror(ODR o, char *message); YAZ_EXPORT void odr_setprint(ODR o, FILE *file); YAZ_EXPORT ODR odr_createmem(int direction); @@ -242,13 +244,13 @@ YAZ_EXPORT int ber_tag(ODR o, void *p, int zclass, int tag, int *constructed, int opt); YAZ_EXPORT int ber_enctag(ODR o, int zclass, int tag, int constructed); YAZ_EXPORT int ber_dectag(const unsigned char *buf, int *zclass, - int *tag, int *constructed); + int *tag, int *constructed, int max); YAZ_EXPORT int odr_bool(ODR o, int **p, int opt, const char *name); YAZ_EXPORT int odr_integer(ODR o, int **p, int opt, const char *name); YAZ_EXPORT int odr_enum(ODR o, int **p, int opt, const char *name); YAZ_EXPORT int odr_implicit_settag(ODR o, int zclass, int tag); YAZ_EXPORT int ber_enclen(ODR o, int len, int lenlen, int exact); -YAZ_EXPORT int ber_declen(const unsigned char *buf, int *len); +YAZ_EXPORT int ber_declen(const unsigned char *buf, int *len, int max); YAZ_EXPORT void odr_prname(ODR o, const char *name); YAZ_EXPORT int ber_null(ODR o); YAZ_EXPORT int odr_null(ODR o, Odr_null **p, int opt, const char *name); diff --git a/odr/ber_any.c b/odr/ber_any.c index 3b7f69a..00388cd 100644 --- a/odr/ber_any.c +++ b/odr/ber_any.c @@ -2,7 +2,7 @@ * Copyright (c) 1995-2003, Index Data * See the file LICENSE for details. * - * $Id: ber_any.c,v 1.23 2003-02-21 12:08:58 adam Exp $ + * $Id: ber_any.c,v 1.24 2003-03-11 11:03:31 adam Exp $ */ #if HAVE_CONFIG_H #include @@ -13,14 +13,13 @@ int ber_any(ODR o, Odr_any **p) { int res; - int left = o->size - (o->bp - o->buf); switch (o->direction) { case ODR_DECODE: - if ((res = completeBER(o->bp, left)) <= 0) /* FIX THIS */ + if ((res = completeBER(o->bp, odr_max(o))) <= 0) /* FIX THIS */ { - o->error = OPROTO; + odr_seterror(o, OPROTO, 2); return 0; } (*p)->buf = (unsigned char *)odr_malloc(o, res); @@ -32,7 +31,7 @@ int ber_any(ODR o, Odr_any **p) if (odr_write(o, (*p)->buf, (*p)->len) < 0) return 0; return 1; - default: o->error = OOTHER; return 0; + default: odr_seterror(o, OOTHER, 3); return 0; } } @@ -48,13 +47,13 @@ int completeBER(const unsigned char *buf, int len) return 0; if (!buf[0] && !buf[1]) return 0; - if ((res = ber_dectag(b, &zclass, &tag, &cons)) <= 0) + if ((res = ber_dectag(b, &zclass, &tag, &cons, len)) <= 0) return 0; if (res > len) return 0; b += res; len -= res; - if ((res = ber_declen(b, &ll)) <= 0) + if ((res = ber_declen(b, &ll, len)) <= 0) return 0; if (res > len) return 0; diff --git a/odr/ber_bit.c b/odr/ber_bit.c index e82c2d5..33ce6b1 100644 --- a/odr/ber_bit.c +++ b/odr/ber_bit.c @@ -3,7 +3,7 @@ * See the file LICENSE for details. * Sebastian Hammer, Adam Dickmeiss * - * $Id: ber_bit.c,v 1.14 2003-01-06 08:20:27 adam Exp $ + * $Id: ber_bit.c,v 1.15 2003-03-11 11:03:31 adam Exp $ * */ #if HAVE_CONFIG_H @@ -20,9 +20,9 @@ int ber_bitstring(ODR o, Odr_bitmask *p, int cons) switch (o->direction) { case ODR_DECODE: - if ((res = ber_declen(o->bp, &len)) < 0) + if ((res = ber_declen(o->bp, &len, odr_max(o))) < 0) { - o->error = OPROTO; + odr_seterror(o, OPROTO, 4); return 0; } o->bp += res; @@ -37,16 +37,21 @@ int ber_bitstring(ODR o, Odr_bitmask *p, int cons) /* primitive bitstring */ if (len < 0) { - o->error = OOTHER; + odr_seterror(o, OOTHER, 5); return 0; } if (len == 0) return 1; if (len - 1 > ODR_BITMASK_SIZE) { - o->error = OOTHER; + odr_seterror(o, OOTHER, 6); return 0; } + if (len > odr_max(o)) + { + odr_seterror(o, OOTHER, 7); + return 0; + } o->bp++; /* silently ignore the unused-bits field */ len--; memcpy(p->bits + p->top + 1, o->bp, len); @@ -64,6 +69,6 @@ int ber_bitstring(ODR o, Odr_bitmask *p, int cons) return 0; return 1; case ODR_PRINT: return 1; - default: o->error = OOTHER; return 0; + default: odr_seterror(o, OOTHER, 8); return 0; } } diff --git a/odr/ber_bool.c b/odr/ber_bool.c index 20a8a35..7ce8dc2 100644 --- a/odr/ber_bool.c +++ b/odr/ber_bool.c @@ -3,7 +3,7 @@ * See the file LICENSE for details. * Sebastian Hammer, Adam Dickmeiss * - * $Id: ber_bool.c,v 1.13 2003-01-06 08:20:27 adam Exp $ + * $Id: ber_bool.c,v 1.14 2003-03-11 11:03:31 adam Exp $ */ #if HAVE_CONFIG_H @@ -29,17 +29,17 @@ int ber_boolean(ODR o, int *val) #endif return 1; case ODR_DECODE: - if ((res = ber_declen(o->bp, &len)) < 0) + if ((res = ber_declen(o->bp, &len, odr_max(o))) < 0) { - o->error = OPROTO; + odr_seterror(o, OPROTO, 9); return 0; } - if (len != 1) + o->bp+= res; + if (len != 1 || odr_max(o) < len) { - o->error = OPROTO; + odr_seterror(o, OPROTO, 10); return 0; } - o->bp+= res; *val = *o->bp; o->bp++; #ifdef ODR_DEBUG @@ -48,6 +48,6 @@ int ber_boolean(ODR o, int *val) return 1; case ODR_PRINT: return 1; - default: o->error = OOTHER; return 0; + default: odr_seterror(o, OOTHER, 11); return 0; } } diff --git a/odr/ber_int.c b/odr/ber_int.c index e5a59ab..21aa01f 100644 --- a/odr/ber_int.c +++ b/odr/ber_int.c @@ -3,7 +3,7 @@ * See the file LICENSE for details. * Sebastian Hammer, Adam Dickmeiss * - * $Id: ber_int.c,v 1.21 2003-01-06 08:20:27 adam Exp $ + * $Id: ber_int.c,v 1.22 2003-03-11 11:03:31 adam Exp $ */ #if HAVE_CONFIG_H #include @@ -21,7 +21,7 @@ #include "odr-priv.h" static int ber_encinteger(ODR o, int val); -static int ber_decinteger(const unsigned char *buf, int *val); +static int ber_decinteger(const unsigned char *buf, int *val, int max); int ber_integer(ODR o, int *val) { @@ -30,9 +30,9 @@ int ber_integer(ODR o, int *val) switch (o->direction) { case ODR_DECODE: - if ((res = ber_decinteger(o->bp, val)) <= 0) + if ((res = ber_decinteger(o->bp, val, odr_max(o))) <= 0) { - o->error = OPROTO; + odr_seterror(o, OPROTO, 50); return 0; } o->bp += res; @@ -42,7 +42,7 @@ int ber_integer(ODR o, int *val) return 0; return 1; case ODR_PRINT: return 1; - default: o->error = OOTHER; return 0; + default: odr_seterror(o, OOTHER, 51); return 0; } } @@ -51,25 +51,19 @@ int ber_integer(ODR o, int *val) */ int ber_encinteger(ODR o, int val) { - int lenpos; int a, len; union { int i; unsigned char c[sizeof(int)]; } tmp; - lenpos = odr_tell(o); - if (odr_putc(o, 0) < 0) /* dummy */ - return -1; tmp.i = htonl(val); /* ensure that that we're big-endian */ for (a = 0; a < (int) sizeof(int) - 1; a++) /* skip superfluous octets */ if (!((tmp.c[a] == 0 && !(tmp.c[a+1] & 0X80)) || (tmp.c[a] == 0XFF && (tmp.c[a+1] & 0X80)))) break; len = sizeof(int) - a; - if (odr_write(o, (unsigned char*) tmp.c + a, len) < 0) - return -1; - odr_seek(o, ODR_S_SET, lenpos); if (ber_enclen(o, len, 1, 1) != 1) return -1; - odr_seek(o, ODR_S_END, 0); + if (odr_write(o, (unsigned char*) tmp.c + a, len) < 0) + return -1; #ifdef ODR_DEBUG fprintf(stderr, "[val=%d]", val); #endif @@ -79,16 +73,18 @@ int ber_encinteger(ODR o, int val) /* * Returns: Number of bytes read or 0 if no match, -1 if error. */ -int ber_decinteger(const unsigned char *buf, int *val) +int ber_decinteger(const unsigned char *buf, int *val, int max) { const unsigned char *b = buf; unsigned char fill; int res, len, remains; union { int i; unsigned char c[sizeof(int)]; } tmp; - if ((res = ber_declen(b, &len)) < 0) + if ((res = ber_declen(b, &len, max)) < 0) return -1; - if (len > (int) sizeof(int)) /* let's be reasonable, here */ + if (len+res > max || len < 0) /* out of bounds or indefinite encoding */ + return -1; + if (len > (int) sizeof(int)) /* let's be reasonable, here */ return -1; b+= res; diff --git a/odr/ber_len.c b/odr/ber_len.c index 88602bd..b4fdba6 100644 --- a/odr/ber_len.c +++ b/odr/ber_len.c @@ -3,7 +3,7 @@ * See the file LICENSE for details. * Sebastian Hammer, Adam Dickmeiss * - * $Id: ber_len.c,v 1.11 2003-01-06 08:20:27 adam Exp $ + * $Id: ber_len.c,v 1.12 2003-03-11 11:03:31 adam Exp $ */ #if HAVE_CONFIG_H #include @@ -84,11 +84,13 @@ int ber_enclen(ODR o, int len, int lenlen, int exact) * len = -1 indefinite. * len >= 0 Length. */ -int ber_declen(const unsigned char *buf, int *len) +int ber_declen(const unsigned char *buf, int *len, int max) { const unsigned char *b = buf; int n; + if (max < 1) + return -1; if (*b == 0X80) /* Indefinite */ { *len = -1; @@ -109,13 +111,17 @@ int ber_declen(const unsigned char *buf, int *len) return -1; /* indefinite long form */ n = *b & 0X7F; + if (n >= max) + return -1; *len = 0; b++; - while (n--) + while (--n >= 0) { *len <<= 8; *len |= *(b++); } + if (*len < 0) + return -1; #ifdef ODR_DEBUG fprintf(stderr, "[len=%d]", *len); #endif diff --git a/odr/ber_null.c b/odr/ber_null.c index a883a81..3b84a1d 100644 --- a/odr/ber_null.c +++ b/odr/ber_null.c @@ -3,7 +3,7 @@ * See the file LICENSE for details. * Sebastian Hammer, Adam Dickmeiss * - * $Id: ber_null.c,v 1.13 2003-01-06 08:20:27 adam Exp $ + * $Id: ber_null.c,v 1.14 2003-03-11 11:03:31 adam Exp $ */ #if HAVE_CONFIG_H #include @@ -26,9 +26,14 @@ int ber_null(ODR o) #endif return 1; case ODR_DECODE: + if (odr_max(o) < 1) + { + odr_seterror(o, OPROTO, 39); + return 0; + } if (*(o->bp++) != 0X00) { - o->error = OPROTO; + odr_seterror(o, OPROTO, 12); return 0; } #ifdef ODR_DEBUG @@ -36,6 +41,6 @@ int ber_null(ODR o) #endif return 1; case ODR_PRINT: return 1; - default: o->error = OOTHER; return 0; + default: odr_seterror(o, OOTHER, 13); return 0; } } diff --git a/odr/ber_oct.c b/odr/ber_oct.c index e2ba432..a332846 100644 --- a/odr/ber_oct.c +++ b/odr/ber_oct.c @@ -3,7 +3,7 @@ * See the file LICENSE for details. * Sebastian Hammer, Adam Dickmeiss * - * $Id: ber_oct.c,v 1.20 2003-01-06 08:20:27 adam Exp $ + * $Id: ber_oct.c,v 1.21 2003-03-11 11:03:31 adam Exp $ */ #if HAVE_CONFIG_H #include @@ -20,9 +20,9 @@ int ber_octetstring(ODR o, Odr_oct *p, int cons) switch (o->direction) { case ODR_DECODE: - if ((res = ber_declen(o->bp, &len)) < 0) + if ((res = ber_declen(o->bp, &len, odr_max(o))) < 0) { - o->error = OPROTO; + odr_seterror(o, OPROTO, 14); return 0; } o->bp += res; @@ -37,9 +37,14 @@ int ber_octetstring(ODR o, Odr_oct *p, int cons) /* primitive octetstring */ if (len < 0) { - o->error = OOTHER; + odr_seterror(o, OOTHER, 15); return 0; } + if (len > odr_max(o)) + { + odr_seterror(o, OOTHER, 16); + return 0; + } if (len + 1 > p->size - p->len) { c = (unsigned char *)odr_malloc(o, p->size += len + 1); @@ -65,6 +70,6 @@ int ber_octetstring(ODR o, Odr_oct *p, int cons) return 0; return 1; case ODR_PRINT: return 1; - default: o->error = OOTHER; return 0; + default: odr_seterror(o, OOTHER, 17); return 0; } } diff --git a/odr/ber_oid.c b/odr/ber_oid.c index 0f744fa..905a482 100644 --- a/odr/ber_oid.c +++ b/odr/ber_oid.c @@ -3,7 +3,7 @@ * See the file LICENSE for details. * Sebastian Hammer, Adam Dickmeiss * - * $Id: ber_oid.c,v 1.14 2003-01-06 08:20:27 adam Exp $ + * $Id: ber_oid.c,v 1.15 2003-03-11 11:03:31 adam Exp $ */ #if HAVE_CONFIG_H #include @@ -20,14 +20,14 @@ int ber_oidc(ODR o, Odr_oid *p) switch (o->direction) { case ODR_DECODE: - if ((res = ber_declen(o->bp, &len)) < 1) + if ((res = ber_declen(o->bp, &len, odr_max(o))) < 1) { - o->error = OPROTO; + odr_seterror(o, OPROTO, 18); return 0; } if (len < 0) { - o->error = OPROTO; + odr_seterror(o, OPROTO, 19); return 0; } o->bp += res; @@ -36,6 +36,11 @@ int ber_oidc(ODR o, Odr_oid *p) *p = -1; return 1; } + if (len > odr_max(o)) + { + odr_seterror(o, OPROTO, 20); + return 0; + } p[0] = *o->bp / 40; if (p[0] > 2) p[0] = 2; @@ -50,7 +55,7 @@ int ber_oidc(ODR o, Odr_oid *p) { if (!len) { - o->error = OPROTO; + odr_seterror(o, OPROTO, 21); return 0; } p[pos] <<= 7; @@ -70,7 +75,7 @@ int ber_oidc(ODR o, Odr_oid *p) return 0; if (p[0] < 0 && p[1] <= 0) { - o->error = ODATA; + odr_seterror(o, ODATA, 23); return 0; } for (pos = 1; p[pos] >= 0; pos++) @@ -96,12 +101,13 @@ int ber_oidc(ODR o, Odr_oid *p) odr_seek(o, ODR_S_SET, lenp); if (ber_enclen(o, (end - lenp) - 1, 1, 1) != 1) { - o->error = OOTHER; + odr_seterror(o, OOTHER, 52); return 0; } odr_seek(o, ODR_S_END, 0); return 1; default: - o->error = OOTHER; return 0; + odr_seterror(o, OOTHER, 22); + return 0; } } diff --git a/odr/ber_tag.c b/odr/ber_tag.c index 9172075..0df6014 100644 --- a/odr/ber_tag.c +++ b/odr/ber_tag.c @@ -3,7 +3,7 @@ * See the file LICENSE for details. * Sebastian Hammer, Adam Dickmeiss * - * $Id: ber_tag.c,v 1.24 2003-01-06 08:20:27 adam Exp $ + * $Id: ber_tag.c,v 1.25 2003-03-11 11:03:31 adam Exp $ */ #if HAVE_CONFIG_H #include @@ -44,7 +44,7 @@ int ber_tag(ODR o, void *p, int zclass, int tag, int *constructed, int opt) if (!*pp) { if (!opt) - o->error = OREQUIRED; + odr_seterror(o, OREQUIRED, 24); return 0; } if ((rd = ber_enctag(o, zclass, tag, *constructed)) < 0) @@ -59,15 +59,17 @@ int ber_tag(ODR o, void *p, int zclass, int tag, int *constructed, int opt) if (o->op->stackp > -1 && !odr_constructed_more(o)) { if (!opt) - o->error = OREQUIRED; + odr_seterror(o, OREQUIRED, 25); return 0; } if (odr_ber_tag->lclass < 0) { - if ((odr_ber_tag->br = ber_dectag(o->bp, &odr_ber_tag->lclass, - &odr_ber_tag->ltag, &odr_ber_tag->lcons)) <= 0) + if ((odr_ber_tag->br = + ber_dectag(o->bp, &odr_ber_tag->lclass, + &odr_ber_tag->ltag, &odr_ber_tag->lcons, + odr_max(o))) <= 0) { - o->error = OPROTO; + odr_seterror(o, OPROTO, 26); return 0; } #ifdef ODR_DEBUG @@ -87,15 +89,15 @@ int ber_tag(ODR o, void *p, int zclass, int tag, int *constructed, int opt) else { if (!opt) - o->error = OREQUIRED; + odr_seterror(o, OREQUIRED, 27); return 0; } case ODR_PRINT: if (!*pp && !opt) - o->error = OREQUIRED; + odr_seterror(o,OREQUIRED, 28); return *pp != 0; default: - o->error = OOTHER; + odr_seterror(o, OOTHER, 29); return 0; } } @@ -144,23 +146,26 @@ int ber_enctag(ODR o, int zclass, int tag, int constructed) /* ber_dectag * Decode BER identifier octets. Return number of bytes read or -1 for error. */ -int ber_dectag(const unsigned char *buf, int *zclass, int *tag, int *constructed) +int ber_dectag(const unsigned char *b, int *zclass, int *tag, + int *constructed, int max) { - const unsigned char *b = buf; + int l = 1; + + if (l > max) + return -1; *zclass = *b >> 6; *constructed = (*b >> 5) & 0X01; if ((*tag = *b & 0x1F) <= 30) return 1; - b++; *tag = 0; do { + if (l >= max) + return -1; *tag <<= 7; - *tag |= *b & 0X7F; - if (b - buf >= 5) /* Precaution */ - return -1; + *tag |= b[l] & 0X7F; } - while (*(b++) & 0X80); - return b - buf; + while (b[l++] & 0X80); + return l; } diff --git a/odr/dumpber.c b/odr/dumpber.c index de57132..fcf2e3d 100644 --- a/odr/dumpber.c +++ b/odr/dumpber.c @@ -3,7 +3,7 @@ * See the file LICENSE for details. * Sebastian Hammer, Adam Dickmeiss * - * $Id: dumpber.c,v 1.14 2003-01-06 08:20:27 adam Exp $ + * $Id: dumpber.c,v 1.15 2003-03-11 11:03:31 adam Exp $ */ #if HAVE_CONFIG_H #include @@ -21,7 +21,7 @@ static int do_dumpBER(FILE *f, const char *buf, int len, int level, int offset) return 0; if (!buf[0] && !buf[1]) return 0; - if ((res = ber_dectag((unsigned char*)b, &zclass, &tag, &cons)) <= 0) + if ((res = ber_dectag((unsigned char*)b, &zclass, &tag, &cons, len)) <= 0) return 0; if (res > len) { @@ -41,7 +41,7 @@ static int do_dumpBER(FILE *f, const char *buf, int len, int level, int offset) "GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", "[UNIV 28]" }; - if (tag < 28) + if (tag >= 0 && tag < 28) fprintf(f, "%s", nl[tag]); else fprintf(f, "[UNIV %d]", tag); @@ -54,14 +54,9 @@ static int do_dumpBER(FILE *f, const char *buf, int len, int level, int offset) taglen = res; len -= res; bp = b; - if ((res = ber_declen((unsigned char*)b, &ll)) <= 0) + if ((res = ber_declen((unsigned char*)b, &ll, len)) <= 0) { - fprintf(f, "bad length\n"); - return 0; - } - if (res > len) - { - fprintf(f, "Unexpected end of buffer\n"); + fprintf(f, "\n%*sBad length\n", level*4+5, ""); return 0; } lenlen = res; @@ -74,15 +69,24 @@ static int do_dumpBER(FILE *f, const char *buf, int len, int level, int offset) fprintf(f, " tl=%d, ll=%d\n", taglen, lenlen); if (!cons) { - if (ll < 0) + if (ll < 0 || ll > len) { - fprintf(f, "Bad length on primitive type.\n"); + fprintf(f, "%*sBad length on primitive type. ll=%d len=%d\n", + level*4+5, "", ll, len); return 0; } return ll + (b - buf); } if (ll >= 0) + { + if (ll > len) + { + fprintf(f, "%*sBad length of constructed type ll=%d len=%d.\n", + level*4+5, "", ll, len); + return 0; + } len = ll; + } /* constructed - cycle through children */ while ((ll == -1 && len >= 2) || (ll >= 0 && len)) { @@ -90,17 +94,23 @@ static int do_dumpBER(FILE *f, const char *buf, int len, int level, int offset) break; if (!(res = do_dumpBER(f, b, len, level + 1, offset + (b - buf)))) { - fprintf(f, "Dump of content element failed.\n"); + fprintf(f, "%*sDump of content element failed.\n", level*4+5, ""); return 0; } b += res; len -= res; + if (len < 0) + { + fprintf(f, "%*sBad length\n", level*4+5, ""); + return 0; + } } if (ll == -1) { if (len < 2) { - fprintf(f, "Buffer too short in indefinite lenght.\n"); + fprintf(f, "%*sBuffer too short in indefinite length.\n", + level*4+5, ""); return 0; } return (b - buf) + 2; diff --git a/odr/odr-priv.h b/odr/odr-priv.h index 0c60940..01b1a4f 100644 --- a/odr/odr-priv.h +++ b/odr/odr-priv.h @@ -23,7 +23,7 @@ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. * - * $Id: odr-priv.h,v 1.3 2003-01-06 08:20:27 adam Exp $ + * $Id: odr-priv.h,v 1.4 2003-03-11 11:03:31 adam Exp $ */ #ifndef ODR_PRIV_H @@ -40,6 +40,9 @@ struct Odr_ber_tag { /* used to be statics in ber_tag... */ int lcons; }; +#define odr_max(o) ((o)->size - ((o)->bp - (o)->buf)) +#define odr_offset(o) ((o)->bp - (o)->buf) + struct Odr_private { /* stack for constructed types */ #define ODR_MAX_STACK 50 @@ -48,6 +51,7 @@ struct Odr_private { struct Odr_ber_tag odr_ber_tag; yaz_iconv_t iconv_handle; + int error_id; }; /* Private macro. diff --git a/odr/odr.c b/odr/odr.c index 1f8a625..7bd3fae 100644 --- a/odr/odr.c +++ b/odr/odr.c @@ -2,7 +2,7 @@ * Copyright (c) 1995-2003, Index Data * See the file LICENSE for details. * - * $Id: odr.c,v 1.40 2003-02-12 15:06:43 adam Exp $ + * $Id: odr.c,v 1.41 2003-03-11 11:03:31 adam Exp $ * */ #if HAVE_CONFIG_H @@ -54,6 +54,19 @@ int odr_geterror(ODR o) return o->error; } +int odr_geterrorx(ODR o, int *x) +{ + if (x) + *x = o->op->error_id; + return o->error; +} + +void odr_seterror(ODR o, int error, int id) +{ + o->error = error; + o->op->error_id = id; +} + void odr_setprint(ODR o, FILE *file) { o->print = file; @@ -95,7 +108,7 @@ ODR odr_createmem(int direction) void odr_reset(ODR o) { - o->error = ONONE; + odr_seterror(o, ONONE, 0); o->bp = o->buf; odr_seek(o, ODR_S_SET, 0); o->top = 0; @@ -142,3 +155,4 @@ char *odr_getbuf(ODR o, int *len, int *size) *size = o->size; return (char*) o->buf; } + diff --git a/odr/odr_any.c b/odr/odr_any.c index aa5b08f..0def5ee 100644 --- a/odr/odr_any.c +++ b/odr/odr_any.c @@ -3,7 +3,7 @@ * See the file LICENSE for details. * Sebastian Hammer, Adam Dickmeiss * - * $Id: odr_any.c,v 1.12 2003-01-06 08:20:27 adam Exp $ + * $Id: odr_any.c,v 1.13 2003-03-11 11:03:31 adam Exp $ */ #if HAVE_CONFIG_H #include @@ -33,6 +33,6 @@ int odr_any(ODR o, Odr_any **p, int opt, const char *name) return 1; *p = 0; if (!opt) - o->error = OREQUIRED; + odr_seterror(o, OREQUIRED, 53); return opt; } diff --git a/odr/odr_choice.c b/odr/odr_choice.c index 15ef87c..51f6b2f 100644 --- a/odr/odr_choice.c +++ b/odr/odr_choice.c @@ -3,7 +3,7 @@ * See the file LICENSE for details. * Sebastian Hammer, Adam Dickmeiss * - * $Id: odr_choice.c,v 1.21 2003-01-06 08:20:27 adam Exp $ + * $Id: odr_choice.c,v 1.22 2003-03-11 11:03:31 adam Exp $ */ #if HAVE_CONFIG_H #include @@ -53,7 +53,7 @@ int odr_choice(ODR o, Odr_arm arm[], void *p, void *whichp, { if (o->op->stackp > -1 && !odr_constructed_more(o)) return 0; - if (ber_dectag(o->bp, &cl, &tg, &cn) <= 0) + if (ber_dectag(o->bp, &cl, &tg, &cn, odr_max(o)) <= 0) return 0; } else if (o->direction != ODR_DECODE) diff --git a/odr/odr_cons.c b/odr/odr_cons.c index b02842b..806e38c 100644 --- a/odr/odr_cons.c +++ b/odr/odr_cons.c @@ -2,7 +2,7 @@ * Copyright (c) 1995-2003, Index Data * See the file LICENSE for details. * - * $Id: odr_cons.c,v 1.24 2003-01-06 08:20:27 adam Exp $ + * $Id: odr_cons.c,v 1.25 2003-03-11 11:03:31 adam Exp $ * */ #if HAVE_CONFIG_H @@ -38,7 +38,7 @@ int odr_constructed_begin(ODR o, void *p, int zclass, int tag, if (o->op->stackp == ODR_MAX_STACK - 1) { - o->error = OSTACK; + odr_seterror(o, OSTACK, 30); return 0; } o->op->stack[++(o->op->stackp)].lenb = o->bp; @@ -52,15 +52,29 @@ int odr_constructed_begin(ODR o, void *p, int zclass, int tag, o->op->stack[o->op->stackp].lenlen = lenlen; - if (odr_write(o, dummy, lenlen) < 0) /* dummy */ + if (odr_write(o, dummy, lenlen) < 0) /* dummy */ + { + --(o->op->stackp); return 0; + } } else if (o->direction == ODR_DECODE) { - if ((res = ber_declen(o->bp, &o->op->stack[o->op->stackp].len)) < 0) + if ((res = ber_declen(o->bp, &o->op->stack[o->op->stackp].len, + odr_max(o))) < 0) + { + odr_seterror(o, OOTHER, 31); + --(o->op->stackp); return 0; + } o->op->stack[o->op->stackp].lenlen = res; o->bp += res; + if (o->op->stack[o->op->stackp].len > odr_max(o)) + { + odr_seterror(o, OOTHER, 32); + --(o->op->stackp); + return 0; + } } else if (o->direction == ODR_PRINT) { @@ -70,7 +84,8 @@ int odr_constructed_begin(ODR o, void *p, int zclass, int tag, } else { - o->error = OOTHER; + odr_seterror(o, OOTHER, 33); + --(o->op->stackp); return 0; } o->op->stack[o->op->stackp].base = o->bp; @@ -99,7 +114,7 @@ int odr_constructed_end(ODR o) return 0; if (o->op->stackp < 0) { - o->error = OOTHER; + odr_seterror(o, OOTHER, 34); return 0; } switch (o->direction) @@ -114,14 +129,14 @@ int odr_constructed_end(ODR o) } else { - o->error = OOTHER; + odr_seterror(o, OOTHER, 35); return 0; } } else if (o->bp - o->op->stack[o->op->stackp].base != o->op->stack[o->op->stackp].len) { - o->error = OCONLEN; + odr_seterror(o, OCONLEN, 36); return 0; } o->op->stackp--; @@ -132,7 +147,7 @@ int odr_constructed_end(ODR o) if ((res = ber_enclen(o, pos - o->op->stack[o->op->stackp].base_offset, o->op->stack[o->op->stackp].lenlen, 1)) < 0) { - o->error = OLENOV; + odr_seterror(o, OLENOV, 37); return 0; } odr_seek(o, ODR_S_END, 0); @@ -159,7 +174,7 @@ int odr_constructed_end(ODR o) fprintf(o->print, "}\n"); return 1; default: - o->error = OOTHER; + odr_seterror(o, OOTHER, 38); return 0; } } diff --git a/odr/odr_enum.c b/odr/odr_enum.c index 8dc6e84..0dda8bb 100644 --- a/odr/odr_enum.c +++ b/odr/odr_enum.c @@ -3,7 +3,7 @@ * See the file LICENSE for details. * Sebastian Hammer, Adam Dickmeiss * - * $Id: odr_enum.c,v 1.7 2003-01-06 08:20:27 adam Exp $ + * $Id: odr_enum.c,v 1.8 2003-03-11 11:03:31 adam Exp $ */ #if HAVE_CONFIG_H #include @@ -38,7 +38,7 @@ int odr_enum(ODR o, int **p, int opt, const char *name) } if (cons) { - o->error = OPROTO; + odr_seterror(o, OPROTO, 54); return 0; } if (o->direction == ODR_DECODE) diff --git a/odr/odr_int.c b/odr/odr_int.c index 04ffbee..f5a3b33 100644 --- a/odr/odr_int.c +++ b/odr/odr_int.c @@ -3,7 +3,7 @@ * See the file LICENSE for details. * Sebastian Hammer, Adam Dickmeiss * - * $Id: odr_int.c,v 1.17 2003-01-06 08:20:27 adam Exp $ + * $Id: odr_int.c,v 1.18 2003-03-11 11:03:31 adam Exp $ */ #if HAVE_CONFIG_H #include @@ -38,7 +38,7 @@ int odr_integer(ODR o, int **p, int opt, const char *name) } if (cons) { - o->error = OPROTO; + odr_seterror(o, OPROTO, 1); return 0; } if (o->direction == ODR_DECODE) diff --git a/odr/odr_mem.c b/odr/odr_mem.c index a032d4b..43f3c54 100644 --- a/odr/odr_mem.c +++ b/odr/odr_mem.c @@ -2,7 +2,7 @@ * Copyright (c) 1995-2003, Index Data * See the file LICENSE for details. * - * $Id: odr_mem.c,v 1.21 2003-01-06 08:20:27 adam Exp $ + * $Id: odr_mem.c,v 1.22 2003-03-11 11:03:31 adam Exp $ */ #if HAVE_CONFIG_H #include @@ -78,7 +78,7 @@ int odr_write(ODR o, unsigned char *buf, int bytes) { if (o->pos + bytes >= o->size && odr_grow_block(o, bytes)) { - o->error = OSPACE; + odr_seterror(o, OSPACE, 40); return -1; } memcpy(o->buf + o->pos, buf, bytes); @@ -96,7 +96,7 @@ int odr_seek(ODR o, int whence, int offset) offset += o->top; if (offset > o->size && odr_grow_block(o, offset - o->size)) { - o->error = OSPACE; + odr_seterror(o, OSPACE, 41); return -1; } o->pos = offset; diff --git a/odr/odr_null.c b/odr/odr_null.c index 76e3b05..8524f8f 100644 --- a/odr/odr_null.c +++ b/odr/odr_null.c @@ -3,7 +3,7 @@ * See the file LICENSE for details. * Sebastian Hammer, Adam Dickmeiss * - * $Id: odr_null.c,v 1.15 2003-01-06 08:20:27 adam Exp $ + * $Id: odr_null.c,v 1.16 2003-03-11 11:03:31 adam Exp $ */ #if HAVE_CONFIG_H #include @@ -39,7 +39,7 @@ int odr_null(ODR o, Odr_null **p, int opt, const char *name) if (cons) { #ifdef ODR_STRICT_NULL - o->error = OPROTO; + odr_seterror(OPROTO, 42); return 0; #else fprintf(stderr, "odr: Warning: Bad NULL\n"); diff --git a/odr/odr_oct.c b/odr/odr_oct.c index 73b7088..dee25a7 100644 --- a/odr/odr_oct.c +++ b/odr/odr_oct.c @@ -3,7 +3,7 @@ * See the file LICENSE for details. * Sebastian Hammer, Adam Dickmeiss * - * $Id: odr_oct.c,v 1.20 2003-01-06 08:20:27 adam Exp $ + * $Id: odr_oct.c,v 1.21 2003-03-11 11:03:31 adam Exp $ */ #if HAVE_CONFIG_H #include @@ -57,7 +57,7 @@ int odr_octetstring(ODR o, Odr_oct **p, int opt, const char *name) } if (ber_octetstring(o, *p, cons)) return 1; - o->error = OOTHER; + odr_seterror(o, OOTHER, 43); return 0; } @@ -152,7 +152,7 @@ int odr_iconv_string(ODR o, char **p, int opt, const char *name) &outbuf, &outleft); if (ret == (size_t)(-1)) { - o->error = ODATA; + odr_seterror(o, ODATA, 44); return 0; } t->size = t->len = outbuf - (char*) t->buf; @@ -189,7 +189,7 @@ int odr_iconv_string(ODR o, char **p, int opt, const char *name) &outbuf, &outleft); if (ret == (size_t)(-1)) { - o->error = ODATA; + odr_seterror(o, ODATA, 45); return 0; } inleft = outbuf - (char*) *p; diff --git a/odr/odr_oid.c b/odr/odr_oid.c index 5081f73..6d575d1 100644 --- a/odr/odr_oid.c +++ b/odr/odr_oid.c @@ -3,7 +3,7 @@ * See the file LICENSE for details. * Sebastian Hammer, Adam Dickmeiss * - * $Id: odr_oid.c,v 1.18 2003-01-06 08:20:28 adam Exp $ + * $Id: odr_oid.c,v 1.19 2003-03-11 11:03:31 adam Exp $ */ #if HAVE_CONFIG_H #include @@ -33,7 +33,7 @@ int odr_oid(ODR o, Odr_oid **p, int opt, const char *name) return opt; if (cons) { - o->error = OPROTO; + odr_seterror(o, OPROTO, 46); return 0; } if (o->direction == ODR_PRINT) diff --git a/odr/odr_seq.c b/odr/odr_seq.c index c23614b..ab68a76 100644 --- a/odr/odr_seq.c +++ b/odr/odr_seq.c @@ -3,7 +3,7 @@ * See the file LICENSE for details. * Sebastian Hammer, Adam Dickmeiss * - * $Id: odr_seq.c,v 1.29 2003-01-06 08:20:28 adam Exp $ + * $Id: odr_seq.c,v 1.30 2003-03-11 11:03:31 adam Exp $ */ #if HAVE_CONFIG_H @@ -121,7 +121,7 @@ static int odr_sequence_x (ODR o, Odr_fun type, void *p, int *num) } break; default: - o->error = OOTHER; + odr_seterror(o, OOTHER, 47); return 0; } return odr_sequence_end(o); diff --git a/odr/odr_tag.c b/odr/odr_tag.c index 6fa0eb4..8e40213 100644 --- a/odr/odr_tag.c +++ b/odr/odr_tag.c @@ -3,7 +3,7 @@ * See the file LICENSE for details. * Sebastian Hammer, Adam Dickmeiss * - * $Id: odr_tag.c,v 1.13 2003-01-06 08:20:28 adam Exp $ + * $Id: odr_tag.c,v 1.14 2003-03-11 11:03:31 adam Exp $ */ #if HAVE_CONFIG_H #include @@ -15,14 +15,14 @@ int odr_peektag(ODR o, int *zclass, int *tag, int *cons) { if (o->direction != ODR_DECODE) { - o->error = OOTHER; + odr_seterror(o, OOTHER, 48); return 0; } if (o->op->stackp > -1 && !odr_constructed_more(o)) return 0; - if (ber_dectag(o->bp, zclass, tag, cons) <= 0) + if (ber_dectag(o->bp, zclass, tag, cons, odr_max(o)) <= 0) { - o->error = OREQUIRED; + odr_seterror(o, OREQUIRED, 49); return 0; } return 1; -- 1.7.10.4