Fixed bug that caused MARC decode to SEGV for some invalid MARC records.
authorAdam Dickmeiss <adam@indexdata.dk>
Fri, 25 Feb 2005 09:37:53 +0000 (09:37 +0000)
committerAdam Dickmeiss <adam@indexdata.dk>
Fri, 25 Feb 2005 09:37:53 +0000 (09:37 +0000)
Adde marc4 + marc4.xml as a test case for it.

src/marcdisp.c
test/Makefile.am
test/marc4 [new file with mode: 0644]
test/marc4.xml [new file with mode: 0644]

index 6c7ba4c..edabacd 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 1995-2005, Index Data ApS
  * See the file LICENSE for details.
  *
- * $Id: marcdisp.c,v 1.16 2005-02-08 13:51:30 adam Exp $
+ * $Id: marcdisp.c,v 1.17 2005-02-25 09:37:53 adam Exp $
  */
 
 /**
@@ -246,10 +246,10 @@ int yaz_marc_decode_wrbuf (yaz_marc_t mt, const char *buf, int bsize, WRBUF wr)
         if (entry_p >= record_length)
             return -1;
     }
-    if (mt->debug && base_address != entry_p+1)
+    if (base_address != entry_p+1)
     {
        if (produce_warnings)
-           wrbuf_printf (wr,"  <!-- base address not at end of directory "
+           wrbuf_printf (wr,"  <!-- Base address not at end of directory "
                          "base=%d end=%d -->\n", base_address, entry_p+1);
     }
     base_address = entry_p+1;
@@ -277,8 +277,11 @@ int yaz_marc_decode_wrbuf (yaz_marc_t mt, const char *buf, int bsize, WRBUF wr)
            i = data_offset + base_address;
            end_offset = i+data_length-1;
            
-           while (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS &&
-                  i < end_offset)
+           if (data_length <= 0 || data_offset < 0 || end_offset >= record_length)
+               return -1;
+        
+           while (i < end_offset &&
+                   buf[i] != ISO2709_RS && buf[i] != ISO2709_FS)
                i++;
            sz1 = 1+i - (data_offset + base_address);
            if (mt->iconv_cd)
@@ -326,6 +329,15 @@ int yaz_marc_decode_wrbuf (yaz_marc_t mt, const char *buf, int bsize, WRBUF wr)
        entry_p += length_starting;
        i = data_offset + base_address;
        end_offset = i+data_length-1;
+
+       if (data_length <= 0 || data_offset < 0 || end_offset >= record_length)
+       {
+           if (produce_warnings)
+               wrbuf_printf (wr,"  <!-- Bad data-offset=%d or "
+                                   "data-length=%d -->\n",
+                                         data_length, data_offset);
+           break;
+       }
         
        if (mt->debug)
        {
@@ -428,7 +440,8 @@ int yaz_marc_decode_wrbuf (yaz_marc_t mt, const char *buf, int bsize, WRBUF wr)
         }
         if (identifier_flag)
         {
-            while (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS && i < end_offset)
+            while (i < end_offset &&
+                   buf[i] != ISO2709_RS && buf[i] != ISO2709_FS)
             {
                 int i0;
                 i++;
@@ -467,8 +480,9 @@ int yaz_marc_decode_wrbuf (yaz_marc_t mt, const char *buf, int bsize, WRBUF wr)
                     break;
                 }
                 i0 = i;
-                while (buf[i] != ISO2709_RS && buf[i] != ISO2709_IDFS &&
-                       buf[i] != ISO2709_FS && i < end_offset)
+                while (i < end_offset &&
+                       buf[i] != ISO2709_RS && buf[i] != ISO2709_IDFS &&
+                        buf[i] != ISO2709_FS)
                     i++;
                 marc_cdata(mt, buf + i0, i - i0, wr);
 
@@ -485,7 +499,8 @@ int yaz_marc_decode_wrbuf (yaz_marc_t mt, const char *buf, int bsize, WRBUF wr)
         else
         {
             int i0 = i;
-            while (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS && i < end_offset)
+            while (i < end_offset && 
+               buf[i] != ISO2709_RS && buf[i] != ISO2709_FS)
                 i++;
            marc_cdata(mt, buf + i0, i - i0, wr);
            if (mt->xml == YAZ_MARC_ISO2709)
index 6ba430f..cff0364 100644 (file)
@@ -1,6 +1,6 @@
 ## Copyright (C) 1994-2004, Index Data
 ## All rights reserved.
-## $Id: Makefile.am,v 1.4 2004-11-03 22:30:52 adam Exp $
+## $Id: Makefile.am,v 1.5 2005-02-25 09:37:53 adam Exp $
 
 check_PROGRAMS = tsticonv tstnmem tstmatchstr tstwrbuf tstodr tstccl tstlog
 check_SCRIPTS = tstcql.sh tstmarc.sh
@@ -9,7 +9,7 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
 
 EXTRA_DIST = tstodr.asn tstodrcodec.c tstodrcodec.h cqlsample \
  $(check_SCRIPTS) \
- marc1 marc1.xml marc2 marc2.xml marc3 marc3.xml
+ marc1 marc1.xml marc2 marc2.xml marc3 marc3.xml marc4 marc4.xml
 
 YAZCOMP = $(top_srcdir)/util/yaz-asncomp
 YAZCOMPLINE = $(YAZCOMP) -d z.tcl -i yaz -I../include $(YCFLAGS)
diff --git a/test/marc4 b/test/marc4
new file mode 100644 (file)
index 0000000..39d179c
--- /dev/null
@@ -0,0 +1 @@
+0091400914naa  2200337   45  001001700000004000900017008002400026009001000050041000800060041000800068097000700076245003300083300002600116557003300142630001600175630001300191633001000204633000900214648006100223648001600284648005400300J01000600354BAS000500360LKR004200365CAT003000407CAT003000437CAT003000467CAT003900497CAT002600536UID001400562\1e  \1faa00001508\1ffa\1e  \1fai\1frn\1e  \1fa1991\1fbxx\1flnor\1fta\1fv9\1e  \1faa\1fgxx\1e  \1fanor\1e  \1fdeng\1e00\1fa06\1e  \1faByfornyelse ved Ibsen-Ringen\1e  \1fbfarvefoto\1fbplan\1fbsnit\1e  \1faByggekunst\1fj1991\1fv1/2\1fk41-45\1e  \1ffbyfornyelse\1e  \1ffsanering\1e  \1ffNorge\1e  \1ffOslo\1e  \1faTelje Torp Aasen Arkitektkontor\1fcKristian Augustsgate 7B\1e  \1faEng, Dagfin\1e  Granlund, Tom\1fcKristian Augustsgate\1fcPilestredet 19\1e  \1faa\1e  20\1e  \1faITM\1flARK50\1fb0000145\1fy1991\1fi1/2\1fk41-45\1e  \1fa\1fb\1fc20020111\1flARK01\1fh2002\1e  \1fa\1fb\1fc20020111\1flARK01\1fh2116\1e  \1fa\1fb\1fc20021002\1flARK01\1fh1000\1e  \1faICLLOAD\1fb00\1fc20021122\1flARK01\1fh1948\1e  \1fc20030618\1flARK01\1fh1330\1e  \1faa00001508\1e\1d
diff --git a/test/marc4.xml b/test/marc4.xml
new file mode 100644 (file)
index 0000000..8429e20
--- /dev/null
@@ -0,0 +1,9 @@
+<!-- Indicator length at offset 10 should hold a digit. Assuming 2 -->
+<!-- Identifier length at offset 11 should hold a digit. Assuming 2 -->
+<!-- Base address at offsets 12..16 should hold a number. Assuming 0 -->
+<!-- Length implementation at offset 22 should hold a digit. Assuming 0 -->
+<record xmlns="http://www.loc.gov/MARC21/slim">
+  <leader>009140091a22a  22003370 </leader>
+  <!-- Base address not at end of directory base=0 end=402 -->
+  <!-- Bad data-offset=0 or data-length=100170 -->
+</record>