read a PNG, the result will be in the same color type as the PNG (hence "generic")*/
| 4755 | |
| 4756 | /*read a PNG, the result will be in the same color type as the PNG (hence "generic")*/ |
| 4757 | static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h, |
| 4758 | LodePNGState* state, |
| 4759 | const unsigned char* in, size_t insize) { |
| 4760 | unsigned char IEND = 0; |
| 4761 | const unsigned char* chunk; |
| 4762 | unsigned char* idat; /*the data from idat chunks, zlib compressed*/ |
| 4763 | size_t idatsize = 0; |
| 4764 | unsigned char* scanlines = 0; |
| 4765 | size_t scanlines_size = 0, expected_size = 0; |
| 4766 | size_t outsize = 0; |
| 4767 | |
| 4768 | /*for unknown chunk order*/ |
| 4769 | unsigned unknown = 0; |
| 4770 | #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS |
| 4771 | unsigned critical_pos = 1; /*1 = after IHDR, 2 = after PLTE, 3 = after IDAT*/ |
| 4772 | #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ |
| 4773 | |
| 4774 | |
| 4775 | /* safe output values in case error happens */ |
| 4776 | *out = 0; |
| 4777 | *w = *h = 0; |
| 4778 | |
| 4779 | state->error = lodepng_inspect(w, h, state, in, insize); /*reads header and resets other parameters in state->info_png*/ |
| 4780 | if(state->error) return; |
| 4781 | |
| 4782 | if(lodepng_pixel_overflow(*w, *h, &state->info_png.color, &state->info_raw)) { |
| 4783 | CERROR_RETURN(state->error, 92); /*overflow possible due to amount of pixels*/ |
| 4784 | } |
| 4785 | |
| 4786 | /*the input filesize is a safe upper bound for the sum of idat chunks size*/ |
| 4787 | idat = (unsigned char*)lodepng_malloc(insize); |
| 4788 | if(!idat) CERROR_RETURN(state->error, 83); /*alloc fail*/ |
| 4789 | |
| 4790 | chunk = &in[33]; /*first byte of the first chunk after the header*/ |
| 4791 | |
| 4792 | /*loop through the chunks, ignoring unknown chunks and stopping at IEND chunk. |
| 4793 | IDAT data is put at the start of the in buffer*/ |
| 4794 | while(!IEND && !state->error) { |
| 4795 | unsigned chunkLength; |
| 4796 | const unsigned char* data; /*the data in the chunk*/ |
| 4797 | |
| 4798 | /*error: size of the in buffer too small to contain next chunk*/ |
| 4799 | if((size_t)((chunk - in) + 12) > insize || chunk < in) { |
| 4800 | if(state->decoder.ignore_end) break; /*other errors may still happen though*/ |
| 4801 | CERROR_BREAK(state->error, 30); |
| 4802 | } |
| 4803 | |
| 4804 | /*length of the data of the chunk, excluding the length bytes, chunk type and CRC bytes*/ |
| 4805 | chunkLength = lodepng_chunk_length(chunk); |
| 4806 | /*error: chunk length larger than the max PNG chunk size*/ |
| 4807 | if(chunkLength > 2147483647) { |
| 4808 | if(state->decoder.ignore_end) break; /*other errors may still happen though*/ |
| 4809 | CERROR_BREAK(state->error, 63); |
| 4810 | } |
| 4811 | |
| 4812 | if((size_t)((chunk - in) + chunkLength + 12) > insize || (chunk + chunkLength + 12) < in) { |
| 4813 | CERROR_BREAK(state->error, 64); /*error: size of the in buffer too small to contain next chunk*/ |
| 4814 | } |
no test coverage detected