Description: Autogenerated patch header for a single-debian-patch file.
 The delta against upstream is either kept as a single patch, or maintained
 in some VCS, and exported as a single patch instead of more manageable
 atomic patches.
Forwarded: not-needed

---
--- djvulibre-3.5.30.1.orig/libdjvu/ByteStream.cpp
+++ djvulibre-3.5.30.1/libdjvu/ByteStream.cpp
@@ -1073,9 +1073,15 @@ ByteStream::create(const GURL &url,char
             {
               MemoryMapByteStream *rb = new MemoryMapByteStream();
               retval = rb;
-              GUTF8String errmessage = rb->init(fd,true);
+              /* Keep the fd on failure: the fdopen() fallback below still
+                 needs it, and closing it here lets another thread reuse the
+                 number in between. A successful mmap holds its own reference,
+                 so the fd can go right away. */
+              GUTF8String errmessage = rb->init(fd,false);
               if(errmessage.length())
                 retval=0;
+              else
+                close(fd);
             }
 #endif
           if (! retval)
@@ -1131,11 +1137,18 @@ ByteStream::create(const int fd,char con
   {
     MemoryMapByteStream *rb=new MemoryMapByteStream();
     retval=rb;
-    GUTF8String errmessage=rb->init(fd,closeme);
+    /* Same as in the GURL overload: never let init() close the fd,
+       the fdopen() fallback below reuses that very number when
+       closeme is set (dup() is only done when it isn't). */
+    GUTF8String errmessage=rb->init(fd,false);
     if(errmessage.length())
     {
       retval=0;
     }
+    else if(closeme)
+    {
+      close(fd);
+    }
   }
   if(!retval)
 #endif
--- djvulibre-3.5.30.1.orig/libdjvu/MMRDecoder.cpp
+++ djvulibre-3.5.30.1/libdjvu/MMRDecoder.cpp
@@ -590,7 +590,7 @@ MMRDecoder::scanruns(const unsigned shor
   for(a0=0,rle=0,b1=*pr++;a0 < width;)
     {
       // Check for buffer overflow
-      if (xr > lineruns+width+2 || pr > prevruns+width+2 || pr < prevruns)
+      if (xr > lineruns+width+2 || pr > prevruns+width+2 || pr < prevruns || a0 < 0)
 	G_THROW(invalid_mmr_data);
       // Process MMR codes
       const int c=mrtable->decode(src);
@@ -795,8 +795,10 @@ const unsigned char *
 MMRDecoder::scanrle(const bool invert, const unsigned char **endptr)
 {
   // Obtain run lengths
-  const unsigned short *xr = scanruns();
-  if (!xr) return 0;
+  const unsigned short *xre;
+  const unsigned short *xr = scanruns(&xre);
+  if (!xr)
+    return 0;
   unsigned char *p=line;
   // Process inversion
   if (invert)
@@ -812,6 +814,7 @@ MMRDecoder::scanrle(const bool invert, c
   // Encode lenghts using the RLE format
   for(int a0=0;a0 < width;)
   {
+    if (xr > xre) return 0;
     int count = *xr++;
     a0 += count;
     GBitmap::append_run(p, count);
@@ -829,6 +832,7 @@ const unsigned char *
 MMRDecoder::scanline(void)
 {
   // Obtain run lengths
+  const unsigned short *xre;
   const unsigned short *xr = scanruns();
   if (!xr) return 0;
   // Allocate data buffer if needed
@@ -838,6 +842,7 @@ MMRDecoder::scanline(void)
   int a0color = 0;
   while (a0 < width)
     {
+      if (xr > xre) return 0;
       int a1 = a0 + *xr++;
       while (a0<a1 && a0<width)
         line[a0++] = a0color;
@@ -898,7 +903,8 @@ MMRDecoder::decode(GP<ByteStream> gbs)
       for(; bandline >= 0; bandline--,line--)
       {
         // Decode one scanline
-        const unsigned short *s = dcd.scanruns();
+        const unsigned short *send;
+        const unsigned short *s = dcd.scanruns(&send);
         if (s)
         {
 	  // Loop on blocks
@@ -908,6 +914,8 @@ MMRDecoder::decode(GP<ByteStream> gbs)
           bool c = !!invert;
           while (x < width)
             {
+              if (s > send)
+                G_THROW(invalid_mmr_data);
               int xend = x + *s++;
               while (b<blocksperline)
                 {
--- djvulibre-3.5.30.1.orig/libdjvu/ddjvuapi.cpp
+++ djvulibre-3.5.30.1/libdjvu/ddjvuapi.cpp
@@ -4105,4 +4105,10 @@ ddjvu_get_DjVuDocument(ddjvu_document_t
   return document->doc;
 }
 
+DDJVUAPI miniexp_t
+ ddjvu_get_anno_from_ByteStream(GP<ByteStream> annobs)
+{
+  return get_bytestream_anno(annobs);
+}
+
 
--- djvulibre-3.5.30.1.orig/libdjvu/ddjvuapi.h
+++ djvulibre-3.5.30.1/libdjvu/ddjvuapi.h
@@ -1663,6 +1663,9 @@ union ddjvu_message_s {
 } // extern "C"
 #endif
 
+#ifdef __cplusplus
+# ifndef NOT_USING_DJVU_NAMESPACE
+
 /* ddjvu_get_DjVuImage ---
    ddjvu_get_DjVuDocument ---
    These functions provide an access to the libdjvu objects 
@@ -1672,8 +1675,6 @@ union ddjvu_message_s {
    after the libdjvu header files <"DjVuImage.h"> and
    <"DjVuDocument.h">. */
 
-#ifdef __cplusplus
-# ifndef NOT_USING_DJVU_NAMESPACE
 #  ifdef _DJVUIMAGE_H
 DDJVUAPI GP<DjVuImage>
 ddjvu_get_DjVuImage(ddjvu_page_t *page);
@@ -1682,6 +1683,18 @@ ddjvu_get_DjVuImage(ddjvu_page_t *page);
 DDJVUAPI GP<DjVuDocument>
 ddjvu_get_DjVuDocument(ddjvu_document_t *document);
 #  endif
+
+/* ddjvu_get_anno_from_ByteStream ---
+   This function provides the means to decode annotation chunks in a
+   libdjvu ByteStream. It is only declared in C++ when file
+   <"ddjvuapi.h"> is included after the libdjvu header files
+   <"ByteStream.h"> */
+
+#  ifdef _BYTESTREAM_H
+DDJVUAPI miniexp_t
+ddjvu_get_anno_from_ByteStream(GP<ByteStream> annobs);
+#  endif
+
 # endif
 #endif
 
--- djvulibre-3.5.30.1.orig/tools/djvused.cpp
+++ djvulibre-3.5.30.1/tools/djvused.cpp
@@ -69,7 +69,6 @@
 #include "DjVuMessageLite.h"
 #include "BSByteStream.h"
 #include "DjVuText.h"
-#include "DjVuAnno.h"
 #include "DjVuInfo.h"
 #include "IFFByteStream.h"
 #include "DataPool.h"
@@ -77,6 +76,8 @@
 #include "DjVuFile.h"
 #include "DjVmNav.h"
 #include "common.h"
+#include "libdjvu/ddjvuapi.h"
+#include "libdjvu/miniexp.h"
 
 static bool modified = false;
 static bool verbose = false;
@@ -1121,38 +1122,35 @@ command_set_ant(ParsingByteStream &pbs)
 }
 
 static void
-print_meta(IFFByteStream &iff, ByteStream &out)
+print_meta(ByteStream &out)
 {
-  GUTF8String chkid;  
-  while (iff.get_chunk(chkid))
+  if (! g().file)
+    return;
+  GP<ByteStream> anno = g().file->get_anno();
+  if (! (anno && anno->size()))
+    return;
+  miniexp_t expr = ddjvu_get_anno_from_ByteStream(anno);
+  if (miniexp_consp(expr))
     {
-      bool ok = false;
-      GP<DjVuANT> ant=DjVuANT::create();
-      if (chkid == "ANTz") {
-          GP<ByteStream> bsiff=BSByteStream::create(iff.get_bytestream());
-          ant->decode(*bsiff);
-          ok = true;
-      } else if (chkid == "ANTa") {
-        ant->decode(*iff.get_bytestream());
-        ok = true;
-      }
-      if (ok)
+      miniexp_t *keys = ddjvu_anno_get_metadata_keys(expr);
+      if (keys)
         {
-          { // extra nesting for windows
-            for (GPosition pos=ant->metadata; pos; ++pos)
-            { 
-              GUTF8String tmp;
-              tmp=ant->metadata.key(pos);
-              out.writestring(tmp); 
-              out.write8('\t');
-              tmp=ant->metadata[pos];
-              print_c_string((const char*)tmp, tmp.length(), out, utf8);
-              out.write8('\n');
+          for (int i = 0; keys[i]; ++i)
+            {
+              const char *key = miniexp_to_name(keys[i]);
+              const char *val = ddjvu_anno_get_metadata(expr, keys[i]);
+              if (key && val)
+                {
+                  out.writestring(GUTF8String(key));
+                  out.write8('\t');
+                  print_c_string(val, strlen(val), out, utf8);
+                  out.write8('\n');
+                }
             }
-          }
+          free(keys);
         }
-      iff.close_chunk();
     }
+
 }
 
 void 
@@ -1171,10 +1169,7 @@ command_print_meta(ParsingByteStream &)
   if ( g().file )
     {
       GP<ByteStream> out=ByteStream::create("w");
-      GP<ByteStream> anno = g().file->get_anno();
-      if (! (anno && anno->size())) return;
-      GP<IFFByteStream> iff=IFFByteStream::create(anno); 
-      print_meta(*iff,*out);
+      print_meta(*out);
     }
 }
 
@@ -1303,28 +1298,24 @@ command_set_meta(ParsingByteStream &pbs)
 }
 
 static void
-print_xmp(IFFByteStream &iff, ByteStream &out)
+print_xmp(ByteStream &out)
 {
-  GUTF8String chkid;  
-  while (iff.get_chunk(chkid))
+  if (! g().file)
+    return;
+  GP<ByteStream> anno = g().file->get_anno();
+  if (! (anno && anno->size()))
+    return;
+  miniexp_t expr = ddjvu_get_anno_from_ByteStream(anno);
+  if (miniexp_consp(expr))
     {
-      bool ok = false;
-      GP<DjVuANT> ant=DjVuANT::create();
-      if (chkid == "ANTz") {
-          GP<ByteStream> bsiff=BSByteStream::create(iff.get_bytestream());
-          ant->decode(*bsiff);
-          ok = true;
-      } else if (chkid == "ANTa") {
-        ant->decode(*iff.get_bytestream());
-        ok = true;
-      }
-      if (ok && ant->xmpmetadata.length()>0)
+      const char *xmp = ddjvu_anno_get_xmp(expr);
+      if (xmp)
         {
-          out.writestring(ant->xmpmetadata);
+          out.writestring(GUTF8String(xmp));
           out.write8('\n');
         }
-      iff.close_chunk();
     }
+
 }
 
 void 
@@ -1343,10 +1334,7 @@ command_print_xmp(ParsingByteStream &)
   if ( g().file )
     {
       GP<ByteStream> out=ByteStream::create("w");
-      GP<ByteStream> anno = g().file->get_anno();
-      if (! (anno && anno->size())) return;
-      GP<IFFByteStream> iff=IFFByteStream::create(anno); 
-      print_xmp(*iff,*out);
+      print_xmp(*out);
     }
 }
 
