Fixes for random/hostile BER.
authorAdam Dickmeiss <adam@indexdata.dk>
Tue, 11 Mar 2003 11:03:30 +0000 (11:03 +0000)
committerAdam Dickmeiss <adam@indexdata.dk>
Tue, 11 Mar 2003 11:03:30 +0000 (11:03 +0000)
24 files changed:
include/yaz/odr.h
odr/ber_any.c
odr/ber_bit.c
odr/ber_bool.c
odr/ber_int.c
odr/ber_len.c
odr/ber_null.c
odr/ber_oct.c
odr/ber_oid.c
odr/ber_tag.c
odr/dumpber.c
odr/odr-priv.h
odr/odr.c
odr/odr_any.c
odr/odr_choice.c
odr/odr_cons.c
odr/odr_enum.c
odr/odr_int.c
odr/odr_mem.c
odr/odr_null.c
odr/odr_oct.c
odr/odr_oid.c
odr/odr_seq.c
odr/odr_tag.c

index a95d9e1..b9bd91f 100644 (file)
@@ -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);
index 3b7f69a..00388cd 100644 (file)
@@ -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 <config.h>
 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;
index e82c2d5..33ce6b1 100644 (file)
@@ -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;
     }
 }
index 20a8a35..7ce8dc2 100644 (file)
@@ -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;
     }
 }
index e5a59ab..21aa01f 100644 (file)
@@ -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 <config.h>
@@ -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;
 
index 88602bd..b4fdba6 100644 (file)
@@ -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 <config.h>
@@ -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
index a883a81..3b84a1d 100644 (file)
@@ -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 <config.h>
@@ -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;
     }
 }
index e2ba432..a332846 100644 (file)
@@ -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 <config.h>
@@ -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;
     }
 }
index 0f744fa..905a482 100644 (file)
@@ -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 <config.h>
@@ -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;
     }
 }
index 9172075..0df6014 100644 (file)
@@ -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 <config.h>
@@ -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;
 }
index de57132..fcf2e3d 100644 (file)
@@ -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 <config.h>
@@ -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;
index 0c60940..01b1a4f 100644 (file)
@@ -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.
index 1f8a625..7bd3fae 100644 (file)
--- 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;
 }
+
index aa5b08f..0def5ee 100644 (file)
@@ -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 <config.h>
@@ -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;
 }    
index 15ef87c..51f6b2f 100644 (file)
@@ -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 <config.h>
@@ -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)
index b02842b..806e38c 100644 (file)
@@ -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;
     }
 }
index 8dc6e84..0dda8bb 100644 (file)
@@ -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 <config.h>
@@ -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)
index 04ffbee..f5a3b33 100644 (file)
@@ -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 <config.h>
@@ -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)
index a032d4b..43f3c54 100644 (file)
@@ -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 <config.h>
@@ -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;
index 76e3b05..8524f8f 100644 (file)
@@ -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 <config.h>
@@ -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");
index 73b7088..dee25a7 100644 (file)
@@ -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 <config.h>
@@ -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;
index 5081f73..6d575d1 100644 (file)
@@ -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 <config.h>
@@ -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)
index c23614b..ab68a76 100644 (file)
@@ -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);
index 6fa0eb4..8e40213 100644 (file)
@@ -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 <config.h>
@@ -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;