pike.git / src / modules / Image / encodings / png.c

version» Context lines:

pike.git/src/modules/Image/encodings/png.c:4:   || for more information.   */      #include "global.h"   #include "image_machine.h"      #include "object.h"   #include "interpret.h"   #include "svalue.h"   #include "threads.h" + #include "array.h"   #include "mapping.h"   #include "pike_error.h"   #include "stralloc.h"   #include "builtin_functions.h"   #include "operators.h"   #include "module_support.h" -  + #include "pike_types.h"      #include "image.h"   #include "colortable.h"    -  + #include "bignum.h" + #include "bitvector.h" +    #ifdef __MINGW32__   /* encodings.a will never contain a crc32 symbol. */   #define DYNAMIC_MODULE   #endif      #define sp Pike_sp      extern struct program *image_colortable_program;   extern struct program *image_program;      #ifdef DYNAMIC_MODULE   typedef unsigned INT32 (_crc32)(unsigned INT32, unsigned char*,    unsigned INT32); - typedef void (_pack)(struct pike_string*, dynamic_buffer*, int, int, int); - typedef void (_unpack)(struct pike_string*, dynamic_buffer*, int); + typedef void (_pack)(struct pike_string*, struct byte_buffer*, int, int, int); + typedef void (_unpack)(struct pike_string*, struct byte_buffer*, int);   static _crc32 *crc32;   static _pack *zlibmod_pack;   static _unpack *zlibmod_unpack;   #else   extern unsigned INT32 crc32(unsigned INT32, unsigned char*, unsigned INT32); - extern void zlibmod_pack(struct pike_string*, dynamic_buffer*, int, int, int); - extern void zlibmod_unpack(struct pike_string*, dynamic_buffer*, int); + extern void zlibmod_pack(struct pike_string*, struct byte_buffer*, int, int, int); + extern void zlibmod_unpack(struct pike_string*, struct byte_buffer*, int);   #endif      static struct pike_string *param_palette;   static struct pike_string *param_spalette;   static struct pike_string *param_image;   static struct pike_string *param_alpha; - static struct pike_string *param_type; +    static struct pike_string *param_bpp;   static struct pike_string *param_background;   static struct pike_string *param_zlevel;   static struct pike_string *param_zstrategy;      /*! @module Image    */      /*! @module PNG    *! Support for encoding and decoding the Portable Network Graphics    *! format, PNG.    *!    *! @note    *! This module uses zlib.    */    - static INLINE void push_nbo_32bit(size_t x) + static inline void push_nbo_32bit(size_t x)   {    char buf[4]; -  buf[0] = DO_NOT_WARN((char)(x>>24)); -  buf[1] = DO_NOT_WARN((char)(x>>16)); -  buf[2] = DO_NOT_WARN((char)(x>>8)); -  buf[3] = DO_NOT_WARN((char)(x)); +  buf[0] = (char)(x>>24); +  buf[1] = (char)(x>>16); +  buf[2] = (char)(x>>8); +  buf[3] = (char)(x);    push_string(make_shared_binary_string(buf,4));   }    - static INLINE unsigned long int_from_32bit(const unsigned char *data) + static inline unsigned long int_from_32bit(const unsigned char *data)   { -  return (data[0]<<24)|(data[1]<<16)|(data[2]<<8)|(data[3]); +  /* NB: Avoid sign-extension in implicit cast from int to unsigned long. */ +  return (((unsigned long)data[0])<<24)|(data[1]<<16)|(data[2]<<8)|(data[3]);   }      #define int_from_16bit(X) _int_from_16bit((unsigned char*)(X)) - static INLINE unsigned long _int_from_16bit(const unsigned char *data) + static inline unsigned long _int_from_16bit(const unsigned char *data)   {    return (data[0]<<8)|(data[1]);   }    - static INLINE COLORTYPE _png_c16(unsigned long z,int bpp) + static inline COLORTYPE _png_c16(unsigned long z,int bpp)   {    switch (bpp)    { -  case 16: return DO_NOT_WARN((COLORTYPE)(z>>8)); -  case 4: return DO_NOT_WARN((COLORTYPE)(z*17)); -  case 2: return DO_NOT_WARN((COLORTYPE)(z*0x55)); -  case 1: return DO_NOT_WARN((COLORTYPE)(z*255)); -  default: return DO_NOT_WARN((COLORTYPE)z); +  case 16: return (COLORTYPE)(z>>8); +  case 4: return (COLORTYPE)(z*17); +  case 2: return (COLORTYPE)(z*0x55); +  case 1: return (COLORTYPE)(z*255); +  default: return (COLORTYPE)z;    }   }      static void push_png_chunk(const char *type, /* 4 bytes */    struct pike_string *data) /* (freed) or on stack */   {    /*    * 0: 4 bytes of length of data block (=n)    * 4: 4 bytes of chunk type    * 8: n bytes of data
pike.git/src/modules/Image/encodings/png.c:115:    push_string(make_shared_binary_string(type,4));    push_string(data);    f_add(2);    push_nbo_32bit(crc32(0,(unsigned char*)sp[-1].u.string->str,    (unsigned INT32)(sp[-1].u.string->len)));    f_add(3);   }      static void png_decompress(int style)   { -  dynamic_buffer buf; +  struct byte_buffer buf;    ONERROR err;       if (style!=0)    Pike_error("Internal error: Illegal decompression style %d.\n",style);    -  initialize_buf(&buf); -  SET_ONERROR(err, toss_buffer, &buf); +  buffer_init(&buf); +  SET_ONERROR(err, buffer_free, &buf);    zlibmod_unpack(Pike_sp[-1].u.string, &buf, 0);    UNSET_ONERROR(err);       pop_stack(); -  push_string(low_free_buf(&buf)); +  push_string(buffer_finish_pike_string(&buf));   }      static void png_compress(int style, int zlevel, int zstrategy)   { -  dynamic_buffer buf; +  struct byte_buffer buf;    ONERROR err;       if (style)    Pike_error("Internal error: Illegal decompression style %d.\n",style);    -  initialize_buf(&buf); -  SET_ONERROR(err, toss_buffer, &buf); +  buffer_init(&buf); +  SET_ONERROR(err, buffer_free, &buf);    zlibmod_pack(Pike_sp[-1].u.string, &buf, zlevel, zstrategy, 15);    UNSET_ONERROR(err);       pop_stack(); -  push_string(low_free_buf(&buf)); +  push_string(buffer_finish_pike_string(&buf));   }      /*! @decl string _chunk(string type, string data)    *! Encodes a PNG chunk.    *!    *! @note    *! Please read about the PNG file format.    */      static void image_png__chunk(INT32 args)
pike.git/src/modules/Image/encodings/png.c:202:    *! @note    *! Please read about the PNG file format.    *! Support for decoding cHRM, gAMA, sBIT, hIST, pHYs, tIME,    *! tEXt and zTXt chunks are missing.    */      static void image_png___decode(INT32 args)   {    int nocrc=0;    unsigned char *data; +  struct array *res;    size_t len;    struct pike_string *str; -  int n=0; +     ONERROR uwp;       if (args<1) -  SIMPLE_TOO_FEW_ARGS_ERROR("Image.PNG.__decode", 1); +  SIMPLE_WRONG_NUM_ARGS_ERROR("__decode", 1);    if (TYPEOF(sp[-args]) != T_STRING) -  SIMPLE_BAD_ARG_ERROR("Image.PNG.__decode", 1, "string"); +  SIMPLE_ARG_TYPE_ERROR("__decode", 1, "string");       if (args>1 &&    (TYPEOF(sp[1-args]) != T_INT ||    sp[1-args].u.integer!=0))    nocrc=1;       add_ref(str=sp[-args].u.string);    data=(unsigned char*)str->str;    len=str->len;   
pike.git/src/modules/Image/encodings/png.c:241:    data[7]!=10)    {    free_string(str);    push_int(0);    return;    }       SET_ONERROR(uwp,do_free_string,str);    len-=8; data+=8;    +  check_stack(20); +  BEGIN_AGGREGATE_ARRAY(10); +     while (len>8)    {    unsigned long x;    x=int_from_32bit(data);    push_string(make_shared_binary_string((char*)data+4,4));    len-=8;    data+=8; -  +     if (x>len)    {    push_string(make_shared_binary_string((char*)data,len));    push_int(0);    f_aggregate(3); -  n++; +  DO_AGGREGATE_ARRAY(20);    break;    } -  +     push_string(make_shared_binary_string((char*)data,x));    if (!nocrc && x+4<=len)    push_int( crc32(crc32(0,NULL,0),data-4,x+4) ==    int_from_32bit(data+x) );    else    push_int(0);    f_aggregate(3); -  n++; +  DO_AGGREGATE_ARRAY(20); +     if (x+4>len) break; -  +  +  if( int_from_32bit((unsigned char *)data) == 0x49454e44 ) /* IEND */ +  break; +     len-=x+4;    data+=x+4;    } -  +  CALL_AND_UNSET_ONERROR(uwp);    -  UNSET_ONERROR(uwp); -  free_string(str); -  f_aggregate(n); +  END_AGGREGATE_ARRAY;   }      /*! @decl mapping _decode(string|array data)    *! @decl mapping _decode(string|array data, mapping options)    *! Decode a PNG image file.    *!    *! @param options    *! @mapping    *! @member string|array|Image.Colortable "colortable"    *! A replacement color table to be used instead of the one
pike.git/src/modules/Image/encodings/png.c:417:    d=(unsigned char*)ps->str;    s=data;       sbb=(bpp+7)>>3; /* rounding up */       for (;;)    {    if (!len || !ysize--)    {    if (pos) *pos=s; +  if (d - STR0(ps) < ps->len) { +  /* Should we throw an error here, instead? +  * This case means that there is extra +  * IDAT data, when we have already processed all +  * scanlines specified in the IHDR +  * /arne +  */ +  memset(d, 0, ps->len - (d - STR0(ps))); +  }    return end_shared_string(ps);    }    x=xsize;      #if 0    fprintf(stderr,    "%05d 0x%08lx %02x %02x %02x > %02x < %02x %02x %02x "    "len=%ld xsize=%d sbb=%d next=0x%08lx d=0x%lx nd=0x%lx\n",    ysize+1,(unsigned long)s,    s[-3],s[-2],s[-1],s[0],s[1],s[2],s[3],
pike.git/src/modules/Image/encodings/png.c:510:    *d=(unsigned char)(d[-xsize]+*s); /* de facto */    else *d=*s;       d++;    s++;    }    if (len) len--;       break;    default: +  free_string(ps);    Pike_error("Unsupported subfilter %d (filter %d)\n", s[-1],type);    }    }   }    - static int _png_write_rgb(rgb_group *w1, + static void _png_write_rgb(rgb_group *w1,    rgb_group *wa1,    int type,int bpp,    const unsigned char *s,    size_t len,    unsigned long width,    size_t n,    const struct neo_colortable *ct,    const struct pike_string *trns)   { -  /* returns 1 if alpha channel, 0 if not */ -  +     static const rgb_group white={255,255,255};    static const rgb_group grey4[4]={{0,0,0},{85,85,85},    {170,170,170},{255,255,255}};    static const rgb_group black={0,0,0};       rgb_group *d1=w1;    rgb_group *da1=wa1;       size_t n0=n;   
pike.git/src/modules/Image/encodings/png.c:614:    }    break;    case 16:    if (n>len/2) n=len/2;    while (n)    {    d1->r=d1->g=d1->b=*(s++); d1++; s++;    n--;    }    break; -  default: -  Pike_error("Image.PNG._decode: Unsupported color type/bit depth %d (grey)/%d bit.\n", -  type,bpp); +     }    if (trns && trns->len==2)    {    rgb_group tr;    tr.r=tr.g=tr.b=_png_c16(int_from_16bit(trns->str),bpp);    n=n0;    d1=w1;    while (n--) *(da1++)=(tr.r==(d1++)->r)?black:white; -  return 1; /* alpha channel */ +     } -  return 0; /* no alpha channel */ +  return;       case 2: /* 8 or 16 bit r,g,b */    switch (bpp)    {    case 8:    if (n>len/3) n=len/3;    while (n)    {    d1->r=*(s++);    d1->g=*(s++);
pike.git/src/modules/Image/encodings/png.c:657:    d1->r=*s;    s += 2;    d1->g=*s;    s += 2;    d1->b=*s;    s += 2;    d1++;    n--;    }    break; -  default: -  Pike_error("Image.PNG._decode: Unsupported color type/bit depth %d (rgb)/%d bit.\n", -  type,bpp); +     }    if (trns && trns->len==6)    {    rgb_group tr;    tr.r=_png_c16(int_from_16bit(trns->str),bpp);    tr.g=_png_c16(int_from_16bit(trns->str+2),bpp);    tr.b=_png_c16(int_from_16bit(trns->str+4),bpp);       n=n0;    d1=w1;    while (n--) *(da1++)=(tr.r==d1->r && tr.g==d1->g && tr.b==d1->b)?black:white,d1++; -  return 1; /* alpha channel */ +     } -  return 0; /* no alpha channel */ +  return;       case 3: /* 1,2,4,8 bit palette index. Alpha might be in palette */ -  if (!ct) -  { -  Pike_error("Image.PNG.decode: No palette, but color type 3 needs one.\n"); -  } -  if (ct->type!=NCT_FLAT) -  { -  Pike_error("Image.PNG.decode: Internal error (created palette isn't flat).\n"); -  } +     mz=ct->u.flat.numentries; -  if (mz==0) -  { -  Pike_error("Image.PNG.decode: Palette is zero entries long;" -  " need at least one color.\n"); -  } +       #define CUTPLTE(X,Z) (((X)>=(Z))?0:(X))    switch (bpp)    {    case 1:    if (n>len*8) n=len*8;    x=width;    if (!trns)    while (n)    {
pike.git/src/modules/Image/encodings/png.c:849:    da1->r=trns->str[m];    da1->g=trns->str[m];    da1->b=trns->str[m];    da1++;    }       s++;    n--;    }    break; -  -  default: -  Pike_error("Image.PNG._decode: Unsupported color type/bit depth %d (palette)/%d bit.\n", -  type,bpp); +     } -  return !!trns; /* alpha channel if trns chunk */ +  return;       case 4: /* 8 or 16 bit grey,a */    switch (bpp)    {    case 8:    if (n>len/2) n=len/2;    while (n)    {    d1->r=d1->g=d1->b=*(s++);    da1->r=da1->g=da1->b=*(s++);
pike.git/src/modules/Image/encodings/png.c:883:    {    d1->r=d1->g=d1->b=*s;    s += 2;    d1++;    da1->r=da1->g=da1->b=*s;    s += 2;    da1++;    n--;    }    break; -  default: -  Pike_error("Image.PNG._decode: Unsupported color type/bit depth %d (grey+a)/%d bit.\n", -  type,bpp); +     } -  return 1; /* alpha channel */ +  return;       case 6: /* 8 or 16 bit r,g,b,a */    switch (bpp)    {    case 8:    if (n>len/4) n=len/4;    while (n)    {    d1->r=*(s++);    d1->g=*(s++);
pike.git/src/modules/Image/encodings/png.c:922:    s += 2;    d1->b=*s;    s += 2;    d1++;    da1->r=da1->g=da1->b=*s;    s += 2;    da1++;    n--;    }    break; -  default: -  Pike_error("Image.PNG._decode: Unsupported color type/bit depth %d (rgba)/%d bit.\n", -  type,bpp); +     } -  return 1; /* alpha channel */ -  default: -  Pike_error("Image.PNG._decode: Unknown color type %d (bit depth %d).\n", -  type,bpp); +  return;    } - #ifdef PIKE_DEBUG -  Pike_fatal("Image.PNG._decode: illegal state\n"); - #endif -  return 0; /* stupid */ +    }      struct png_interlace   {    int y0,yd,x0,xd;   };      static const struct png_interlace adam7[8]=   { {0,8,0,8},    {0,8,4,8},
pike.git/src/modules/Image/encodings/png.c:977:   };      /* IN: IDAT string on stack */   /* OUT: Image object with image (and possibly alpha, depending on    return value) */   static int _png_decode_idat(struct IHDR *ihdr, struct neo_colortable *ct,    struct pike_string *trns)   {    struct pike_string *fs;    struct image *img; -  rgb_group *w1,*wa1; +  rgb_group *w1,*wa1=NULL;    unsigned char *s0; -  unsigned int i,x,y; +  unsigned int i,x,y,got_alpha=0;    ONERROR err, a_err;    -  +  switch(ihdr->type) +  { +  case 0: /* 1,2,4,8 or 16 bit greyscale */ +  switch(ihdr->bpp) +  { +  case 1: +  case 2: +  case 4: +  case 8: +  case 16: +  break; +  default: +  Pike_error("Image.PNG._decode: Unsupported color type/bit depth %d (grey)/%d bit.\n", 0, ihdr->bpp); +  } +  if( trns && trns->len==2 ) +  got_alpha=1; +  break; +  +  case 2: /* 8 or 16 bit r,g,b */ +  switch(ihdr->bpp) +  { +  case 8: +  case 16: +  break; +  default: +  Pike_error("Image.PNG._decode: Unsupported color type/bit depth %d (rgb)/%d bit.\n", 1, ihdr->bpp); +  } +  if( trns && trns->len==6) +  got_alpha=1; +  break; +  +  case 3: /* 1,2,4,8 bit palette index */ +  if (!ct) +  Pike_error("Image.PNG.decode: No palette, but color type 3 needs one.\n"); +  if (ct->type!=NCT_FLAT) +  Pike_error("Image.PNG.decode: Internal error (created palette isn't flat).\n"); +  if (ct->u.flat.numentries==0) +  Pike_error("Image.PNG.decode: Palette is zero entries long;" +  " need at least one color.\n"); +  switch(ihdr->bpp) +  { +  case 1: +  case 2: +  case 4: +  case 8: +  break; +  default: +  Pike_error("Image.PNG._decode: Unsupported color type/bit depth %d (palette)/%d bit.\n", 3, ihdr->bpp); +  } +  got_alpha = !!trns; +  break; +  +  case 4: /* 8 or 16 bit grey */ +  switch(ihdr->bpp) +  { +  case 8: +  case 16: +  break; +  default: +  Pike_error("Image.PNG._decode: Unsupported color type/bit depth %d (palette)/%d bit.\n", 4, ihdr->bpp); +  } +  got_alpha=1; +  break; +  +  case 6: /* 8 ot 16 bit rgba */ +  switch(ihdr->bpp) +  { +  case 8: +  case 16: +  break; +  default: +  Pike_error("Image.PNG._decode: Unsupported color type/bit depth %d (palette)/%d bit.\n", 4, ihdr->bpp); +  } +  got_alpha=1; +  break; +  +  default: +  Pike_error("Image.PNG._decode: Unsupported color type/bit depth %d (palette)/%d bit.\n", ihdr->type, ihdr->bpp); +  } +     png_decompress(ihdr->compression);    if( TYPEOF(sp[-1]) != T_STRING )    Pike_error("Got illegal data from decompression.\n");    -  w1=xalloc(sizeof(rgb_group)*ihdr->width*ihdr->height + RGB_VEC_PAD); -  SET_ONERROR(err, free_and_clear, &w1); +  if (INT32_MUL_OVERFLOW(ihdr->width, ihdr->height) || +  ihdr->width*ihdr->height > (0x7fffffff - RGB_VEC_PAD)/sizeof(rgb_group)) { +  /* Overflow in size calculation below. */ +  Pike_error("Image too large (%d * %d)\n", +  ihdr->width, ihdr->height); +  } +  +  if( got_alpha )    wa1=xalloc(sizeof(rgb_group)*ihdr->width*ihdr->height + RGB_VEC_PAD);    SET_ONERROR(a_err, free_and_clear, &wa1); -  +  w1=xalloc(sizeof(rgb_group)*ihdr->width*ihdr->height + RGB_VEC_PAD); +  SET_ONERROR(err, free_and_clear, &w1);       fs = sp[-1].u.string;       /* --- interlace decoding --- */       switch (ihdr->interlace)    {    case 0: /* none */    fs=_png_unfilter((unsigned char*)fs->str,fs->len,    ihdr->width,ihdr->height,    ihdr->filter,ihdr->type,ihdr->bpp,    NULL);    -  if (!_png_write_rgb(w1,wa1, +  push_string(fs); +  +  _png_write_rgb(w1,wa1,    ihdr->type,ihdr->bpp,    (unsigned char*)fs->str,fs->len,    ihdr->width,    ihdr->width*ihdr->height, -  ct,trns)) -  { -  free(wa1); -  wa1=NULL; -  } -  free_string(fs); +  ct,trns); +  pop_stack();    break;       case 1: /* adam7 */    { -  rgb_group *t1,*ta1; -  ONERROR t_err, ta_err, ds_err; -  int got_alpha = 0; +  rgb_group *t1, *ta1 = NULL; +  ONERROR t_err, ta_err;       /* need arena */    t1=xalloc(sizeof(rgb_group)*ihdr->width*ihdr->height + RGB_VEC_PAD);    SET_ONERROR(t_err, free_and_clear, &t1); -  +  if( got_alpha )    ta1=xalloc(sizeof(rgb_group)*ihdr->width*ihdr->height + RGB_VEC_PAD);    SET_ONERROR(ta_err, free_and_clear, &ta1);       /* loop over adam7 interlace's    and write them to the arena */       s0=(unsigned char*)fs->str;    for (i=0; i<7; i++)    {    struct pike_string *ds;
pike.git/src/modules/Image/encodings/png.c:1050:    unsigned int iwidth = (ihdr->width+xd-1-x0)/xd;    unsigned int iheight = (ihdr->height+yd-1-y0)/yd;       if(!iwidth || !iheight) continue;       ds=_png_unfilter(s0,fs->len-(s0-(unsigned char*)fs->str),    iwidth, iheight,    ihdr->filter,ihdr->type,ihdr->bpp,    &s0);    -  if (_png_write_rgb(w1,wa1,ihdr->type,ihdr->bpp, +  push_string(ds); +  +  _png_write_rgb(w1,wa1,ihdr->type,ihdr->bpp,    (unsigned char*)ds->str,ds->len,    iwidth,    iwidth*iheight, -  ct,trns)) +  ct,trns); +  +  if( got_alpha )    {    da1 = wa1;    for (y=y0; y<ihdr->height; y+=yd)    for (x=x0; x<ihdr->width; x+=xd)    ta1[x+y*ihdr->width]=*(da1++); -  got_alpha = 1; +     }    d1=w1;    for (y=y0; y<ihdr->height; y+=yd)    for (x=x0; x<ihdr->width; x+=xd)    t1[x+y*ihdr->width]=*(d1++);    -  free_string(ds); +  pop_stack();    }    -  free(wa1); +  UNSET_ONERROR(ta_err); +  UNSET_ONERROR(t_err); +     if (got_alpha) { -  +  free(wa1);    wa1 = ta1; -  } else { -  free(ta1); -  wa1 = NULL; +     } -  UNSET_ONERROR(ta_err); +     free(w1); -  w1=t1; -  UNSET_ONERROR(t_err); +  w1 = t1;    }    break;    default:    Pike_error("Unknown interlace type %d.\n", ihdr->interlace);    }       /* Image data now in w1, alpha in wa1 */    pop_stack();    -  UNSET_ONERROR(a_err); -  UNSET_ONERROR(err); -  +     /* Create image object and leave it on the stack */    push_object(clone_object(image_program,0)); -  img=(struct image*)get_storage(sp[-1].u.object,image_program); +  img=get_storage(sp[-1].u.object,image_program);    if (img->img) free(img->img); /* protect from memleak */    img->xsize=ihdr->width;    img->ysize=ihdr->height;    img->img=w1;    -  +  UNSET_ONERROR(err); +     /* Create alpha object and leave it on the stack */    if( wa1 )    {    push_object(clone_object(image_program,0)); -  img=(struct image*)get_storage(sp[-1].u.object,image_program); +  img=get_storage(sp[-1].u.object,image_program);    if (img->img) free(img->img); /* protect from memleak */    img->xsize=ihdr->width;    img->ysize=ihdr->height;    img->img=wa1; -  +  UNSET_ONERROR(a_err);    return 1;    } -  +  UNSET_ONERROR(a_err);       return 0;   }      static void png_free_string(struct pike_string *str)   {    if(str) free_string(str);   }      #define MODE_ALL 0
pike.git/src/modules/Image/encodings/png.c:1136:    struct array *a;    struct mapping *m;    struct neo_colortable *ct=NULL;    struct pike_string *trns=NULL;       int n=0, i;    struct IHDR ihdr={-1,-1,-1,-1,-1,-1,-1};    ONERROR err;       if (args<1) -  SIMPLE_TOO_FEW_ARGS_ERROR("Image.PNG._decode", 1); +  SIMPLE_WRONG_NUM_ARGS_ERROR("_decode", 1);       m=allocate_mapping(10);    push_mapping(m);       if (args>=2)    {    if (TYPEOF(sp[1-args-1]) != T_MAPPING) -  SIMPLE_BAD_ARG_ERROR("Image.PNG._decode", 2, "mapping"); +  SIMPLE_ARG_TYPE_ERROR("_decode", 2, "mapping");       push_svalue(sp+1-args-1);    ref_push_string(param_palette);    f_index(2);    switch (TYPEOF(sp[-1]))    { -  case T_OBJECT: -  push_text("cast"); -  if (TYPEOF(sp[-1]) == T_INT) -  PIKE_ERROR("Image.PNG._decode", -  "Illegal value of option \"palette\".\n", -  sp, args); -  f_index(2); -  push_text("array"); -  f_call_function(2); +     case T_ARRAY:    case T_STRING:    push_object(clone_object(image_colortable_program,1));    -  ct=(struct neo_colortable*)get_storage(sp[-1].u.object, +  /* Fallthrough */ +  case T_OBJECT: +  ct=get_storage(sp[-1].u.object,    image_colortable_program);    if (!ct) -  PIKE_ERROR("Image.PNG._decode", -  "Internal error: cloned colortable isn't colortable.\n", sp, args); +  PIKE_ERROR("_decode", +  "Object isn't colortable.\n", sp, args);    mapping_string_insert(m, param_palette, sp-1);    pop_stack();    break;    case T_INT:    pop_stack();    break;    default: -  PIKE_ERROR("Image.PNG._decode", +  PIKE_ERROR("_decode",    "Illegal value of option \"palette\".\n",    sp, args);    }    }       sp--;    pop_n_elems(args-1);    push_mapping(m);    stack_swap();       if (TYPEOF(sp[-1]) == T_STRING)    {    push_int(1); /* no care crc */    image_png___decode(2);    if (TYPEOF(sp[-1]) != T_ARRAY) -  PIKE_ERROR("Image.PNG._decode", "Not PNG data.\n", sp ,args); +  PIKE_ERROR("_decode", "Not PNG data.\n", sp ,args);    }    else if (TYPEOF(sp[-1]) != T_ARRAY) -  SIMPLE_BAD_ARG_ERROR("Image.PNG._decode", 1, "string"); +  SIMPLE_ARG_TYPE_ERROR("_decode", 1, "string");       a=sp[-1].u.array;       for (i=0; i<a->size; i++)    {    struct array *b = NULL;    unsigned char *data;    size_t len;      #ifdef PIKE_DEBUG
pike.git/src/modules/Image/encodings/png.c:1222:   #else    b = a->item[i].u.array;   #endif       data = (unsigned char *)b->item[1].u.string->str;    len = (size_t)b->item[1].u.string->len;       if (!i &&    int_from_32bit((unsigned char*)b->item[0].u.string->str)    != 0x49484452 ) -  PIKE_ERROR("Imge.PNG.decode", "First chunk isn't IHDR.\n", +  PIKE_ERROR("_decode", "First chunk isn't IHDR.\n",    sp, args);       switch (int_from_32bit((unsigned char*)b->item[0].u.string->str))    {    /* ------ major chunks ------------ */ -  case 0x49484452: /* IHDR */ +  case 0x49484452: { /* IHDR */ +  size_t bytes;    /* header info */ -  if (b->item[1].u.string->len!=13) -  PIKE_ERROR("Image.PNG._decode", +  if (len!=13) +  PIKE_ERROR("_decode",    "Illegal header (IHDR chunk).\n", sp, args);       ihdr.width=int_from_32bit(data+0);    ihdr.height=int_from_32bit(data+4);    -  if( sizeof(rgb_group)*(double)ihdr.width*(double)ihdr.height > -  (double)INT_MAX ) +  if (!ihdr.width || !ihdr.height) +  Pike_error("Image.PNG._decode: Invalid dimensions in IHDR chunk.\n"); +  +  if (DO_SIZE_T_MUL_OVERFLOW(ihdr.width, ihdr.height, &bytes) || +  DO_SIZE_T_MUL_OVERFLOW(bytes, sizeof(rgb_group), &bytes) || +  bytes > INT_MAX) {    Pike_error("Image.PNG._decode: Too large image " -  "(total size exceeds %d bytes (%.0f))\n", INT_MAX, -  sizeof(rgb_group)* -  (double)ihdr.width*(double)ihdr.height); +  "(total size exceeds %d bytes)\n", INT_MAX); +  }       ihdr.bpp=data[8];    ihdr.type=data[9];    ihdr.compression=data[10];    ihdr.filter=data[11];    ihdr.interlace=data[12];    break; -  +  }    case 0x504c5445: /* PLTE */    /* palette info, 3×n bytes */       if (ct) break; /* we have a palette already */       ref_push_string(b->item[1].u.string);    push_object(clone_object(image_colortable_program,1));       if (ihdr.type==3)    { -  ct=(struct neo_colortable*) -  get_storage(sp[-1].u.object,image_colortable_program); +  ct=get_storage(sp[-1].u.object,image_colortable_program);    mapping_string_insert(m, param_palette, sp-1);    }    else    {    mapping_string_insert(m, param_spalette, sp-1);    }    pop_stack();    break;       case 0x49444154: /* IDAT */
pike.git/src/modules/Image/encodings/png.c:1291:    case 0x49454e44: /* IEND */    /* end of file */    break;       /* ------ minor chunks ------------ */       case 0x6348524d: /* cHRM */    {    int i;    if(mode==MODE_IMAGE_ONLY) break; -  if(b->item[1].u.string->len!=32) break; +  if(len!=32) break;    for(i=0; i<32; i+=4) -  push_float((float)int_from_32bit((unsigned char*)b-> -  item[1].u.string->str+i)/100000.0); +  push_float((float)int_from_32bit(data+i)/100000.0);    f_aggregate(8); -  push_text("chroma"); +  push_static_text("chroma");    mapping_insert(m,sp-1,sp-2);    pop_n_elems(2);    }    break;       case 0x73424954: /* sBIT */    { -  int i; +  size_t i;    if(mode==MODE_IMAGE_ONLY) break; -  for(i=0; i<b->item[1].u.string->len; i++) -  push_int(b->item[1].u.string->str[i]); -  f_aggregate(b->item[1].u.string->len); -  push_constant_text("sbit"); +  /* sBIT chunks are not longer than 4 bytes */ +  if (len > 4) break; +  for(i=0; i<len; i++) +  push_int(data[i]); +  f_aggregate(len); +  push_static_text("sbit");    mapping_insert(m,sp-1,sp-2);    pop_n_elems(2);    }    break;       case 0x67414d41: /* gAMA */    if(mode==MODE_IMAGE_ONLY) break; -  if(b->item[1].u.string->len!=4) break; -  push_constant_text("gamma"); -  push_float((float)int_from_32bit((unsigned char*)b-> -  item[1].u.string->str)/100000.0); +  if(len!=4) break; +  push_static_text("gamma"); +  push_float((float)int_from_32bit(data)/100000.0);    mapping_insert(m,sp-2,sp-1);    pop_n_elems(2);    break;    -  case 0x70485973: /* pHYs */ +  case 0x70485973: { /* pHYs */ +  int tmp1, tmp2;    if(mode==MODE_IMAGE_ONLY) break; -  if(b->item[1].u.string->len!=9) break; -  push_int(b->item[1].u.string->str[8]); -  push_int(int_from_32bit((unsigned char*)b-> -  item[1].u.string->str)); -  push_int(int_from_32bit((unsigned char*)b-> -  item[1].u.string->str+4)); +  if(len!=9) break; +  tmp1 = get_unaligned_be32(data); +  tmp2 = get_unaligned_be32(data+4); +  /* the image dimensions are valid in the range +  * 0 .. MAX_INT32 +  */ +  if (data[8] != 0 && data[8] != 1) break; +  if (tmp1 < 0 || tmp2 < 0) break; +  push_int(data[8]); +  push_int(tmp1); +  push_int(tmp2);    f_aggregate(3); -  push_constant_text("physical"); +  push_static_text("physical");    mapping_insert(m,sp-1,sp-2);    pop_n_elems(2);    break; -  -  case 0x6f464673: /* oFFs */ +  } +  case 0x6f464673: { /* oFFs */ +  int tmp1, tmp2;    if(mode==MODE_IMAGE_ONLY) break; -  if(b->item[1].u.string->len!=9) break; -  push_int(b->item[1].u.string->str[8]); -  push_int(int_from_32bit((unsigned char*)b-> -  item[1].u.string->str)); -  push_int(int_from_32bit((unsigned char*)b-> -  item[1].u.string->str+4)); +  if(len!=9) break; +  tmp1 = get_unaligned_be32(data); +  tmp2 = get_unaligned_be32(data+4); +  /* the oFFs image offsets are valid in the range +  * of -MAX_INT32 .. MAX_INT32 */ +  if (data[8] != 0 && data[8] != 1) break; +  if (tmp1 == MIN_INT32 || tmp2 == MIN_INT32) break; +  push_int(data[8]); +  push_int(tmp1); +  push_int(tmp2);    f_aggregate(3); -  push_constant_text("offset"); +  push_static_text("offset");    mapping_insert(m,sp-1,sp-2);    pop_n_elems(2);    break; -  +  }    case 0x74494d45: /* tIME */    if(mode==MODE_IMAGE_ONLY) break; -  if(b->item[1].u.string->len!=7) break; -  push_int(int_from_16bit(b->item[1].u.string->str)); -  push_int(b->item[1].u.string->str[2]); -  push_int(b->item[1].u.string->str[3]); -  push_int(b->item[1].u.string->str[4]); -  push_int(b->item[1].u.string->str[5]); -  push_int(b->item[1].u.string->str[6]); +  if(len!=7) break; +  push_int(int_from_16bit(data)); +  push_int(data[2]); +  push_int(data[3]); +  push_int(data[4]); +  push_int(data[5]); +  push_int(data[6]);    f_aggregate(6); -  push_constant_text("time"); +  push_static_text("time");    mapping_insert(m,sp-1,sp-2);    pop_n_elems(2);    break;       case 0x624b4744: /* bKGD */    if(mode==MODE_IMAGE_ONLY) break;    switch (ihdr.type)    {    case 0:    case 4: -  if (b->item[1].u.string->len==2) +  if (len==2)    { -  int z=_png_c16(b->item[1].u.string->str[0],ihdr.bpp); +  int z=_png_c16(data[0],ihdr.bpp);    push_int(z);    push_int(z);    push_int(z);    }    else    continue;    break;    case 3: -  if (b->item[1].u.string->len!=1 || +  if (len!=1 ||    !ct || ct->type!=NCT_FLAT || -  b->item[1].u.string->str[0] >= -  ct->u.flat.numentries) +  data[0] >= ct->u.flat.numentries)    continue;    else    { -  push_int(ct->u.flat.entries[(int)b->item[1].u.string->str[0]].color.r); -  push_int(ct->u.flat.entries[(int)b->item[1].u.string->str[0]].color.g); -  push_int(ct->u.flat.entries[(int)b->item[1].u.string->str[0]].color.b); +  push_int(ct->u.flat.entries[data[0]].color.r); +  push_int(ct->u.flat.entries[data[0]].color.g); +  push_int(ct->u.flat.entries[data[0]].color.b);    }    break;    default: -  if (b->item[1].u.string->len==6) +  if (len==6)    {    int j;    for (j=0; j<3; j++)    { -  int z=_png_c16(b->item[1].u.string->str[j*2],ihdr.bpp); +  int z=_png_c16(data[j*2],ihdr.bpp);    push_int(z);    }    } else    continue;    break;    }    f_aggregate(3);    mapping_string_insert(m, param_background, sp-1);    pop_stack();    break;       case 0x74524e53: /* tRNS */ -  +  if (trns) break;    trns=b->item[1].u.string;    add_ref(trns); -  +  SET_ONERROR(err, png_free_string, trns);    break;       default:    if(mode==MODE_IMAGE_ONLY) break;       /* Private chunks from Adobe Fireworks: prVW, mkBF, mkBS,    mkBT, mkTS */       ref_push_string(b->item[1].u.string);    ref_push_string(b->item[0].u.string); -  mapping_insert(m,sp-1,sp-2); +  /* do not replace existing entries */ +  low_mapping_insert(m,sp-1,sp-2,0);    pop_n_elems(2);    }    }    -  +     /* on stack: mapping n×string */       if ( mode != MODE_HEADER_ONLY )    { -  if(trns) -  SET_ONERROR(err, png_free_string, &trns); -  +     if (ihdr.type==-1)    PIKE_ERROR("Image.PNG._decode", "Missing header (IHDR chunk).\n",    sp, args);       if (ihdr.type==3 && !ct)    PIKE_ERROR("Image.PNG._decode", "Missing palette (PLTE chunk).\n",    sp, args);       /* Join IDAT blocks */    if (!n)
pike.git/src/modules/Image/encodings/png.c:1463:    f_add(n);       if (_png_decode_idat(&ihdr, ct, trns)==1)    {    mapping_string_insert(m, param_alpha, sp-1);    pop_stack();    }    mapping_string_insert(m, param_image, sp-1);    pop_stack();    -  if(trns) -  UNSET_ONERROR(err); +     }    -  if (trns) +  if (trns) { +  UNSET_ONERROR(err);    png_free_string (trns); -  +  }       if ( mode != MODE_IMAGE_ONLY )    {    push_int(ihdr.type); -  mapping_string_insert(m, param_type, sp-1); +  mapping_string_insert(m, literal_type_string, sp-1);    pop_stack();       push_int(ihdr.bpp);    mapping_string_insert(m, param_bpp, sp-1);    pop_stack();    -  push_constant_text("xsize"); +  push_static_text("xsize");    push_int(ihdr.width);    mapping_insert(m,sp-2,sp-1);    pop_n_elems(2);    -  push_constant_text("ysize"); +  push_static_text("ysize");    push_int(ihdr.height);    mapping_insert(m,sp-2,sp-1);    pop_n_elems(2);    }       pop_stack(); /* remove 'a' from stack */   }         /*! @decl string encode(Image.Image image)
pike.git/src/modules/Image/encodings/png.c:1509:    *! @param options    *! @mapping    *! @member Image.Image "alpha"    *! Use this image as alpha channel (Note: PNG alpha    *! channel is grey. The values are calculated by (r+2g+b)/4.)    *! @member Image.Colortable "palette"    *! Use this as palette for pseudocolor encoding    *! (Note: encoding with alpha channel and pseudocolor    *! at the same time are not supported)    *! @member int(0..9) "zlevel" -  *! The level of z-compression to be applied. Default is 8. +  *! The level of z-compression to be applied. Default is 9.    *! @member int "zstrategy"    *! The type of LZ77 strategy to be used. Possible values are    *! @[Gz.DEFAULT_STRATEGY], @[Gz.FILTERED], @[Gz.HUFFMAN_ONLY],    *! @[Gz.RLE], @[Gz.FIXED]. Default is @[Gz.DEFAULT_STRATEGY].    *! @endmapping    *!    *! @seealso    *! @[__decode]    *!    *! @note    *! Please read some about PNG files.    */      static void image_png_encode(INT32 args)   {    struct image *img = NULL, *alpha = NULL;    rgb_group *s,*sa=NULL;    struct neo_colortable *ct=NULL;       int n=0,y,x,bpp; -  int zlevel=8; +  int zlevel=9;    int zstrategy=0;    char buf[20];       if (!args) -  SIMPLE_TOO_FEW_ARGS_ERROR("Image.PNG.encode", 1); +  SIMPLE_WRONG_NUM_ARGS_ERROR("encode", 1);       if (TYPEOF(sp[-args]) != T_OBJECT || -  !(img=(struct image*) -  get_storage(sp[-args].u.object,image_program))) -  SIMPLE_BAD_ARG_ERROR("Image.PNG.encode", 1, "Image.Image"); +  !(img=get_storage(sp[-args].u.object,image_program))) +  SIMPLE_ARG_TYPE_ERROR("encode", 1, "Image.Image");       if (!img->img) -  PIKE_ERROR("Image.PNG.encode", "No image.\n", sp, args); +  PIKE_ERROR("encode", "No image.\n", sp, args);    -  if (args>1) +  if ((args>1) && !IS_UNDEFINED(sp + 1-args))    {    struct svalue *s;       if (TYPEOF(sp[1-args]) != T_MAPPING) -  SIMPLE_BAD_ARG_ERROR("Image.PNG.encode", 2, "mapping"); +  SIMPLE_ARG_TYPE_ERROR("encode", 2, "mapping");       /* Attribute alpha */    s = low_mapping_string_lookup(sp[1-args].u.mapping, param_alpha);       if( s )    {    if( TYPEOF(*s) == T_OBJECT && -  (alpha=(struct image*) -  get_storage(s->u.object,image_program)) ) +  (alpha=get_storage(s->u.object,image_program)) )    {    if (alpha->xsize!=img->xsize ||    alpha->ysize!=img->ysize) -  PIKE_ERROR("Image.PNG.encode", +  PIKE_ERROR("encode",    "Option (arg 2) \"alpha\"; images differ in size.\n",    sp, args);       if (!alpha->img) -  PIKE_ERROR("Image.PNG.encode", +  PIKE_ERROR("encode",    "Option (arg 2) \"alpha\"; no image\n",    sp, args);    }    else if( !(TYPEOF(*s) == T_INT && s->u.integer==0) ) -  PIKE_ERROR("Image.PNG.encode", +  PIKE_ERROR("encode",    "Option (arg 2) \"alpha\" has illegal type.\n",    sp, args);    }       /* Attribute palette */    s = low_mapping_string_lookup(sp[1-args].u.mapping, param_palette);       if (s && !(TYPEOF(*s) == T_INT && s->u.integer==0))    if (TYPEOF(*s) != T_OBJECT || -  !(ct=(struct neo_colortable*) -  get_storage(s->u.object,image_colortable_program))) -  PIKE_ERROR("Image.PNG.encode", +  !(ct=get_storage(s->u.object,image_colortable_program))) +  PIKE_ERROR("encode",    "Option (arg 2) \"palette\" has illegal type.\n",    sp, args);       /* Attribute zlevel */    s = low_mapping_string_lookup(sp[1-args].u.mapping, param_zlevel);       if ( s )    {    if( TYPEOF(*s) != T_INT ) -  PIKE_ERROR("Image.PNG.encode", +  PIKE_ERROR("encode",    "Option (arg 2) \"zlevel\" has illegal value.\n",    sp, args);    else    zlevel = s->u.integer;    }       /* Attribute zstrategy */    s = low_mapping_string_lookup(sp[1-args].u.mapping, param_zstrategy);    if( s )    {    if ( TYPEOF(*s) != T_INT ) -  PIKE_ERROR("Image.PNG.encode", +  PIKE_ERROR("encode",    "Option (arg 2) \"zstrategy\" has illegal value.\n",    sp, args);    else    zstrategy = s->u.integer;    }    }       sprintf(buf,"%c%c%c%c%c%c%c%c",    137,'P','N','G',13,10,26,10);    push_string(make_shared_binary_string(buf,8));    n++;       if (ct)    {    ptrdiff_t sz;    sz = image_colortable_size(ct);    if (sz>256) -  PIKE_ERROR("Image.PNG.encode", "Palette size to large; " +  PIKE_ERROR("encode", "Palette size to large; "    "PNG doesn't support bigger palettes then 256 colors.\n",    sp, args);    if (sz>16) bpp=8;    else if (sz>4) bpp=4;    else if (sz>2) bpp=2;    else bpp=1;    }    else    bpp=8;   
pike.git/src/modules/Image/encodings/png.c:1655:    0 /* interlace */);    push_string(make_shared_binary_string(buf,13));       push_png_chunk("IHDR",NULL);    n++;       if (ct)    {    struct pike_string *ps;    ps=begin_shared_string(3<<bpp); -  MEMSET(ps->str,0,3<<bpp); +  memset(ps->str,0,3<<bpp);    image_colortable_write_rgb(ct,(unsigned char*)ps->str);    push_string(end_shared_string(ps));    push_png_chunk("PLTE",NULL);    n++;    }       y=img->ysize;    s=img->img;    if (alpha) sa=alpha->img;    if (ct) {    if (alpha) { -  PIKE_ERROR("Image.PNG.encode", +  PIKE_ERROR("encode",    "Colortable and alpha channel not supported "    "at the same time.\n", sp, args);    }    else    {    unsigned char *d;    struct pike_string *ps;    unsigned char *tmp, *ts;       x = img->xsize;
pike.git/src/modules/Image/encodings/png.c:1691:    ps=begin_shared_string( y * ((x*bpp+7)/8+1) );    d=(unsigned char*)ps->str;    ts=tmp;       while (y--)    {    x=img->xsize;    *(d++)=0; /* filter */    if (bpp==8)    { -  MEMCPY(d,ts,x); +  memcpy(d,ts,x);    ts += x;    d += x;    }    else    {    int bit=8-bpp;    *d=0;    while (x--)    {    *d|=(*ts)<<bit;
pike.git/src/modules/Image/encodings/png.c:1802:    *! Decodes a PNG image. The @[options] mapping is the    *! as for @[_decode].    *!    *! @throws    *! Throws upon error in data.    */      static void image_png_decode(INT32 args)   {    if (!args) -  SIMPLE_TOO_FEW_ARGS_ERROR("Image.PNG.decode", 1); +  SIMPLE_WRONG_NUM_ARGS_ERROR("decode", 1);       img_png_decode(args, MODE_IMAGE_ONLY); -  push_constant_text("image"); +  push_static_text("image");    f_index(2);   }      /*! @decl Image.Image decode_alpha(string data, @    *! void|mapping(string:mixed) options)    *! Decodes the alpha channel in a PNG file. The    *! @[options] mapping is the same as for @[_decode].    *!    *! @throws    *! Throws upon error in data.    */      static void image_png_decode_alpha(INT32 args)   {    struct svalue s;    if (!args) -  SIMPLE_TOO_FEW_ARGS_ERROR("Image.PNG.decode_alpha", 1); +  SIMPLE_WRONG_NUM_ARGS_ERROR("decode_alpha", 1);       image_png__decode(args);    assign_svalue_no_free(&s,sp-1); -  push_constant_text("alpha"); +  push_static_text("alpha");    f_index(2);       if (TYPEOF(sp[-1]) == T_INT)    {    push_svalue(&s); -  push_constant_text("xsize"); +  push_static_text("xsize");    f_index(2);    push_svalue(&s); -  push_constant_text("ysize"); +  push_static_text("ysize");    f_index(2);    push_int(255);    push_int(255);    push_int(255);    push_object(clone_object(image_program,5));    }    free_svalue(&s);   }      /*! @endmodule
pike.git/src/modules/Image/encodings/png.c:1861:   /*** module init & exit & stuff *****************************************/      void exit_image_png(void)   {    free_string(param_palette);    free_string(param_spalette);    free_string(param_image);    free_string(param_alpha);    free_string(param_bpp);    free_string(param_background); -  free_string(param_type); +     free_string(param_zlevel);    free_string(param_zstrategy);   }      void init_image_png(void)   {    int gz = 0;   #ifdef DYNAMIC_MODULE    crc32 = PIKE_MODULE_IMPORT(Gz, crc32);    zlibmod_pack = PIKE_MODULE_IMPORT(Gz, zlibmod_pack);    zlibmod_unpack = PIKE_MODULE_IMPORT(Gz, zlibmod_unpack);    if(crc32 && zlibmod_pack && zlibmod_unpack)    gz = 1;   #else -  push_text("Gz.inflate"); +  push_static_text("Gz.inflate");    SAFE_APPLY_MASTER("resolv",1);    if( TYPEOF(Pike_sp[-1]) == T_PROGRAM )    gz = 1;    pop_stack();   #endif       if (gz)    {    ADD_FUNCTION2("_chunk",image_png__chunk,tFunc(tStr tStr,tStr),0,    OPT_TRY_OPTIMIZE);
pike.git/src/modules/Image/encodings/png.c:1912:    ADD_FUNCTION2("encode",image_png_encode,    tFunc(tObj tOr(tVoid,tMap(tStr,tMix)),tStr),0,    OPT_TRY_OPTIMIZE);    }       param_palette=make_shared_string("palette");    param_spalette=make_shared_string("spalette");    param_image=make_shared_string("image");    param_alpha=make_shared_string("alpha");    param_bpp=make_shared_string("bpp"); -  param_type=make_shared_string("type"); +     param_background=make_shared_string("background");    param_zlevel=make_shared_string("zlevel");    param_zstrategy=make_shared_string("zstrategy");   }