From 0d9bcb63b77c7c5d18e7dfefdd7b36d1c6828885 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Thu, 16 Apr 2015 21:31:27 +0200 Subject: [PATCH 1/7] Fixed memory leaks and NULL dereferences. --- winpr/libwinpr/utils/lodepng/lodepng.c | 219 ++++++++++++++++--------- 1 file changed, 143 insertions(+), 76 deletions(-) diff --git a/winpr/libwinpr/utils/lodepng/lodepng.c b/winpr/libwinpr/utils/lodepng/lodepng.c index a65926c41..3f6a73022 100644 --- a/winpr/libwinpr/utils/lodepng/lodepng.c +++ b/winpr/libwinpr/utils/lodepng/lodepng.c @@ -22,6 +22,8 @@ freely, subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ +/* Copyright (c) 2015 Armin Novak + * Modifications fixing various errors. */ #include "lodepng.h" @@ -117,7 +119,11 @@ static unsigned uivector_reserve(uivector* p, size_t allocsize) p->allocsize = newsize; p->data = (unsigned*)data; } - else return 0; /*error: not enough memory*/ + else + { + uivector_cleanup(p); + return 0; /*error: not enough memory*/ + } } return 1; } @@ -175,6 +181,13 @@ typedef struct ucvector size_t allocsize; /*allocated size*/ } ucvector; +static void ucvector_cleanup(void* p) +{ + ((ucvector*)p)->size = ((ucvector*)p)->allocsize = 0; + free(((ucvector*)p)->data); + ((ucvector*)p)->data = NULL; +} + /*returns 1 if success, 0 if failure ==> nothing done*/ static unsigned ucvector_reserve(ucvector* p, size_t allocsize) { @@ -187,7 +200,11 @@ static unsigned ucvector_reserve(ucvector* p, size_t allocsize) p->allocsize = newsize; p->data = (unsigned char*)data; } - else return 0; /*error: not enough memory*/ + else + { + ucvector_cleanup(p); + return 0; /*error: not enough memory*/ + } } return 1; } @@ -202,13 +219,6 @@ static unsigned ucvector_resize(ucvector* p, size_t size) #ifdef LODEPNG_COMPILE_PNG -static void ucvector_cleanup(void* p) -{ - ((ucvector*)p)->size = ((ucvector*)p)->allocsize = 0; - free(((ucvector*)p)->data); - ((ucvector*)p)->data = NULL; -} - static void ucvector_init(ucvector* p) { p->data = NULL; @@ -252,6 +262,14 @@ static unsigned ucvector_push_back(ucvector* p, unsigned char c) #ifdef LODEPNG_COMPILE_PNG #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + +/*free the above pair again*/ +static void string_cleanup(char** out) +{ + free(*out); + *out = NULL; +} + /*returns 1 if success, 0 if failure ==> nothing done*/ static unsigned string_resize(char** out, size_t size) { @@ -261,6 +279,9 @@ static unsigned string_resize(char** out, size_t size) data[size] = 0; /*null termination char*/ *out = data; } + else + string_cleanup(out); + return data != 0; } @@ -271,13 +292,6 @@ static void string_init(char** out) string_resize(out, 0); } -/*free the above pair again*/ -static void string_cleanup(char** out) -{ - free(*out); - *out = NULL; -} - static void string_set(char** out, const char* in) { size_t insize = strlen(in), i = 0; @@ -311,10 +325,11 @@ static void lodepng_set32bitInt(unsigned char* buffer, unsigned value) #endif /*defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)*/ #ifdef LODEPNG_COMPILE_ENCODER -static void lodepng_add32bitInt(ucvector* buffer, unsigned value) +static int lodepng_add32bitInt(ucvector* buffer, unsigned value) { - ucvector_resize(buffer, buffer->size + 4); /*todo: give error if resize failed*/ + if (!ucvector_resize(buffer, buffer->size + 4)) return 0; lodepng_set32bitInt(&buffer->data[buffer->size - 4], value); + return 1; } #endif /*LODEPNG_COMPILE_ENCODER*/ @@ -373,13 +388,19 @@ unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const #ifdef LODEPNG_COMPILE_ZLIB #ifdef LODEPNG_COMPILE_ENCODER /*TODO: this ignores potential out of memory errors*/ -#define addBitToStream(/*size_t**/ bitpointer, /*ucvector**/ bitstream, /*unsigned char*/ bit)\ -{\ - /*add a new byte at the end*/\ - if(((*bitpointer) & 7) == 0) ucvector_push_back(bitstream, (unsigned char)0);\ - /*earlier bit of huffman code is in a lesser significant bit of an earlier byte*/\ - (bitstream->data[bitstream->size - 1]) |= (bit << ((*bitpointer) & 0x7));\ - (*bitpointer)++;\ +static int addBitToStream(size_t* bitpointer, ucvector* bitstream, unsigned char bit) +{ + /*add a new byte at the end*/ + if(((*bitpointer) & 7) == 0) + { + if (!ucvector_push_back(bitstream, (unsigned char)0)) return 83; + } + + /*earlier bit of huffman code is in a lesser significant bit of an earlier byte*/ + (bitstream->data[bitstream->size - 1]) |= (bit << ((*bitpointer) & 0x7)); + (*bitpointer)++; + + return 0; } static void addBitsToStream(size_t* bitpointer, ucvector* bitstream, unsigned value, size_t nbits) @@ -488,6 +509,8 @@ static void HuffmanTree_init(HuffmanTree* tree) tree->tree2d = 0; tree->tree1d = 0; tree->lengths = 0; + tree->maxbitlen = 0; + tree->numcodes = 0; } static void HuffmanTree_cleanup(HuffmanTree* tree) @@ -504,7 +527,7 @@ static unsigned HuffmanTree_make2DTree(HuffmanTree* tree) unsigned treepos = 0; /*position in the tree (1 of the numcodes columns)*/ unsigned n, i; - tree->tree2d = (unsigned*)malloc(tree->numcodes * 2 * sizeof(unsigned)); + tree->tree2d = (unsigned*)calloc(tree->numcodes * 2, sizeof(unsigned)); if(!tree->tree2d) return 83; /*alloc fail*/ /* @@ -571,7 +594,7 @@ static unsigned HuffmanTree_makeFromLengths2(HuffmanTree* tree) uivector_init(&blcount); uivector_init(&nextcode); - tree->tree1d = (unsigned*)malloc(tree->numcodes * sizeof(unsigned)); + tree->tree1d = (unsigned*)calloc(tree->numcodes, sizeof(unsigned)); if(!tree->tree1d) error = 83; /*alloc fail*/ if(!uivector_resizev(&blcount, tree->maxbitlen + 1, 0) @@ -610,7 +633,7 @@ static unsigned HuffmanTree_makeFromLengths(HuffmanTree* tree, const unsigned* b size_t numcodes, unsigned maxbitlen) { unsigned i; - tree->lengths = (unsigned*)malloc(numcodes * sizeof(unsigned)); + tree->lengths = (unsigned*)calloc(numcodes, sizeof(unsigned)); if(!tree->lengths) return 83; /*alloc fail*/ for(i = 0; i < numcodes; i++) tree->lengths[i] = bitlen[i]; tree->numcodes = (unsigned)numcodes; /*number of symbols*/ @@ -841,7 +864,7 @@ static unsigned HuffmanTree_getLength(const HuffmanTree* tree, unsigned index) static unsigned generateFixedLitLenTree(HuffmanTree* tree) { unsigned i, error = 0; - unsigned* bitlen = (unsigned*)malloc(NUM_DEFLATE_CODE_SYMBOLS * sizeof(unsigned)); + unsigned* bitlen = (unsigned*)calloc(NUM_DEFLATE_CODE_SYMBOLS, sizeof(unsigned)); if(!bitlen) return 83; /*alloc fail*/ /*288 possible codes: 0-255=literals, 256=endcode, 257-285=lengthcodes, 286-287=unused*/ @@ -905,11 +928,13 @@ static unsigned huffmanDecodeSymbol(const unsigned char* in, size_t* bp, /* ////////////////////////////////////////////////////////////////////////// */ /*get the tree of a deflated block with fixed tree, as specified in the deflate specification*/ -static void getTreeInflateFixed(HuffmanTree* tree_ll, HuffmanTree* tree_d) +static int getTreeInflateFixed(HuffmanTree* tree_ll, HuffmanTree* tree_d) { - /*TODO: check for out of memory errors*/ - generateFixedLitLenTree(tree_ll); - generateFixedDistanceTree(tree_d); + int rc; + + rc = generateFixedLitLenTree(tree_ll); + if (rc) return rc; + return generateFixedDistanceTree(tree_d); } /*get the tree of a deflated block with dynamic tree, the tree itself is also Huffman compressed with a known tree*/ @@ -1072,7 +1097,16 @@ static unsigned inflateHuffmanBlock(ucvector* out, const unsigned char* in, size HuffmanTree_init(&tree_ll); HuffmanTree_init(&tree_d); - if(btype == 1) getTreeInflateFixed(&tree_ll, &tree_d); + if(btype == 1) + { + error = getTreeInflateFixed(&tree_ll, &tree_d); + if (error) + { + HuffmanTree_cleanup(&tree_ll); + HuffmanTree_cleanup(&tree_d); + return error; + } + } else if(btype == 2) error = getTreeInflateDynamic(&tree_ll, &tree_d, in, bp, inlength); while(!error) /*decode all symbols until end reached, breaks at end code*/ @@ -1598,21 +1632,21 @@ static unsigned deflateNoCompression(ucvector* out, const unsigned char* data, s BTYPE = 0; firstbyte = (unsigned char)(BFINAL + ((BTYPE & 1) << 1) + ((BTYPE & 2) << 1)); - ucvector_push_back(out, firstbyte); + if (!ucvector_push_back(out, firstbyte)) return 83; LEN = 65535; if(datasize - datapos < 65535) LEN = (unsigned)datasize - datapos; NLEN = 65535 - LEN; - ucvector_push_back(out, (unsigned char)(LEN % 256)); - ucvector_push_back(out, (unsigned char)(LEN / 256)); - ucvector_push_back(out, (unsigned char)(NLEN % 256)); - ucvector_push_back(out, (unsigned char)(NLEN / 256)); + if (!ucvector_push_back(out, (unsigned char)(LEN % 256))) return 83; + if (!ucvector_push_back(out, (unsigned char)(LEN / 256))) return 83; + if (!ucvector_push_back(out, (unsigned char)(NLEN % 256))) return 83; + if (!ucvector_push_back(out, (unsigned char)(NLEN / 256))) return 83; /*Decompressed data*/ for(j = 0; j < 65535 && datapos < datasize; j++) { - ucvector_push_back(out, data[datapos++]); + if (!ucvector_push_back(out, data[datapos++])) return 83; } } @@ -1817,17 +1851,17 @@ static unsigned deflateDynamic(ucvector* out, size_t* bp, Hash* hash, if(error) break; if(!uivector_resize(&bitlen_cl, tree_cl.numcodes)) ERROR_BREAK(83 /*alloc fail*/); - for(i = 0; i < tree_cl.numcodes; i++) + for(i = 0; i < tree_cl.numcodes && bitlen_cl.data; i++) { /*lenghts of code length tree is in the order as specified by deflate*/ bitlen_cl.data[i] = HuffmanTree_getLength(&tree_cl, CLCL_ORDER[i]); } - while(bitlen_cl.data[bitlen_cl.size - 1] == 0 && bitlen_cl.size > 4) + while(bitlen_cl.data && bitlen_cl.size > 4 && bitlen_cl.data[bitlen_cl.size - 1] == 0) { /*remove zeros at the end, but minimum size must be 4*/ if(!uivector_resize(&bitlen_cl, bitlen_cl.size - 1)) ERROR_BREAK(83 /*alloc fail*/); } - if(error) break; + if(error || !bitlen_cl.data) break; /* Write everything into the output @@ -1851,15 +1885,20 @@ static unsigned deflateDynamic(ucvector* out, size_t* bp, Hash* hash, /*write the HLIT, HDIST and HCLEN values*/ HLIT = (unsigned)(numcodes_ll - 257); HDIST = (unsigned)(numcodes_d - 1); - HCLEN = (unsigned)bitlen_cl.size - 4; + HCLEN = 0; + if (bitlen_cl.size > 4) + HCLEN = (unsigned)bitlen_cl.size - 4; /*trim zeroes for HCLEN. HLIT and HDIST were already trimmed at tree creation*/ - while(!bitlen_cl.data[HCLEN + 4 - 1] && HCLEN > 0) HCLEN--; + while(HCLEN > 0 && !bitlen_cl.data[HCLEN + 4 - 1]) HCLEN--; addBitsToStream(bp, out, HLIT, 5); addBitsToStream(bp, out, HDIST, 5); addBitsToStream(bp, out, HCLEN, 4); /*write the code lenghts of the code length alphabet*/ - for(i = 0; i < HCLEN + 4; i++) addBitsToStream(bp, out, bitlen_cl.data[i], 3); + if (bitlen_cl.size > 4) + { + for(i = 0; i < HCLEN + 4; i++) addBitsToStream(bp, out, bitlen_cl.data[i], 3); + } /*write the lenghts of the lit/len AND the dist alphabet*/ for(i = 0; i < bitlen_lld_e.size; i++) @@ -1913,8 +1952,15 @@ static unsigned deflateFixed(ucvector* out, size_t* bp, Hash* hash, HuffmanTree_init(&tree_ll); HuffmanTree_init(&tree_d); - generateFixedLitLenTree(&tree_ll); - generateFixedDistanceTree(&tree_d); + error = generateFixedLitLenTree(&tree_ll); + if (error) return error; + + error = generateFixedDistanceTree(&tree_d); + if (error) + { + HuffmanTree_cleanup(&tree_ll); + return error; + } addBitToStream(bp, out, BFINAL); addBitToStream(bp, out, 1); /*first bit of BTYPE*/ @@ -2138,21 +2184,27 @@ unsigned lodepng_zlib_compress(unsigned char** out, size_t* outsize, const unsig /*ucvector-controlled version of the output buffer, for dynamic array*/ ucvector_init_buffer(&outv, *out, *outsize); - ucvector_push_back(&outv, (unsigned char)(CMFFLG / 256)); - ucvector_push_back(&outv, (unsigned char)(CMFFLG % 256)); + if (!ucvector_push_back(&outv, (unsigned char)(CMFFLG / 256))) return 83; + if (!ucvector_push_back(&outv, (unsigned char)(CMFFLG % 256))) return 83; error = deflate(&deflatedata, &deflatesize, in, insize, settings); if(!error) { ADLER32 = adler32(in, (unsigned)insize); - for(i = 0; i < deflatesize; i++) ucvector_push_back(&outv, deflatedata[i]); + for(i = 0; i < deflatesize; i++) + { + if (!ucvector_push_back(&outv, deflatedata[i])) return 83; + } free(deflatedata); - lodepng_add32bitInt(&outv, ADLER32); + error = !lodepng_add32bitInt(&outv, ADLER32); } - *out = outv.data; - *outsize = outv.size; + if (!error) + { + *out = outv.data; + *outsize = outv.size; + } return error; } @@ -4237,7 +4289,7 @@ static unsigned readChunk_zTXt(LodePNGInfo* info, const LodePNGDecompressSetting (unsigned char*)(&data[string2_begin]), length, zlibsettings); if(error) break; - ucvector_push_back(&decoded, 0); + if (!ucvector_push_back(&decoded, 0)) ERROR_BREAK(83); error = lodepng_add_text(info, key, (char*)decoded.data); @@ -4321,7 +4373,7 @@ static unsigned readChunk_iTXt(LodePNGInfo* info, const LodePNGDecompressSetting length, zlibsettings); if(error) break; if(decoded.allocsize < decoded.size) decoded.allocsize = decoded.size; - ucvector_push_back(&decoded, 0); + if (!ucvector_push_back(&decoded, 0)) CERROR_BREAK(error, 83 /*alloc fail*/); } else { @@ -4696,17 +4748,19 @@ static unsigned addChunk(ucvector* out, const char* chunkName, const unsigned ch return 0; } -static void writeSignature(ucvector* out) +static unsigned writeSignature(ucvector* out) { /*8 bytes PNG signature, aka the magic bytes*/ - ucvector_push_back(out, 137); - ucvector_push_back(out, 80); - ucvector_push_back(out, 78); - ucvector_push_back(out, 71); - ucvector_push_back(out, 13); - ucvector_push_back(out, 10); - ucvector_push_back(out, 26); - ucvector_push_back(out, 10); + if (!ucvector_push_back(out, 137)) return 83; + if (!ucvector_push_back(out, 80)) return 83; + if (!ucvector_push_back(out, 78)) return 83; + if (!ucvector_push_back(out, 71)) return 83; + if (!ucvector_push_back(out, 13)) return 83; + if (!ucvector_push_back(out, 10)) return 83; + if (!ucvector_push_back(out, 26)) return 83; + if (!ucvector_push_back(out, 10)) return 83; + + return 0; } static unsigned addChunk_IHDR(ucvector* out, unsigned w, unsigned h, @@ -4716,8 +4770,10 @@ static unsigned addChunk_IHDR(ucvector* out, unsigned w, unsigned h, ucvector header; ucvector_init(&header); - lodepng_add32bitInt(&header, w); /*width*/ - lodepng_add32bitInt(&header, h); /*height*/ + if (!lodepng_add32bitInt(&header, w)) /*width*/ + return 1; + if (!lodepng_add32bitInt(&header, h)) /*height*/ + return 1; ucvector_push_back(&header, (unsigned char)bitdepth); /*bit depth*/ ucvector_push_back(&header, (unsigned char)colortype); /*color type*/ ucvector_push_back(&header, 0); /*compression method*/ @@ -4953,9 +5009,12 @@ static unsigned addChunk_pHYs(ucvector* out, const LodePNGInfo* info) ucvector data; ucvector_init(&data); - lodepng_add32bitInt(&data, info->phys_x); - lodepng_add32bitInt(&data, info->phys_y); - ucvector_push_back(&data, info->phys_unit); + if (!lodepng_add32bitInt(&data, info->phys_x)) + return 1; + if (!lodepng_add32bitInt(&data, info->phys_y)) + return 1; + if (!ucvector_push_back(&data, info->phys_unit)) + return 1; error = addChunk(out, "pHYs", data.data, data.size); ucvector_cleanup(&data); @@ -5092,12 +5151,16 @@ static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, size_t sum[5]; ucvector attempt[5]; /*five filtering attempts, one for each filter type*/ size_t smallest = 0; - unsigned char type, bestType = 0; + unsigned char type, i, bestType = 0; for(type = 0; type < 5; type++) { ucvector_init(&attempt[type]); - if(!ucvector_resize(&attempt[type], linebytes)) return 83; /*alloc fail*/ + if(!ucvector_resize(&attempt[type], linebytes)) + { + for(i=0; i Date: Thu, 16 Apr 2015 21:56:26 +0200 Subject: [PATCH 2/7] Fixed NULL dereference --- winpr/libwinpr/utils/ini.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/winpr/libwinpr/utils/ini.c b/winpr/libwinpr/utils/ini.c index f6d043ac0..b7dd357ca 100644 --- a/winpr/libwinpr/utils/ini.c +++ b/winpr/libwinpr/utils/ini.c @@ -376,7 +376,9 @@ int IniFile_Load(wIniFile* ini) value = beg; IniFile_AddKey(ini, section, name, value); - key = section->keys[section->nKeys - 1]; + key = NULL; + if (section->keys) + key = section->keys[section->nKeys - 1]; } } From 60de56e1bbda852ccc3d7f2d7f72d89125450246 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Thu, 16 Apr 2015 21:56:57 +0200 Subject: [PATCH 3/7] Fixed NULL dereference and double free --- winpr/libwinpr/smartcard/smartcard_pcsc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/winpr/libwinpr/smartcard/smartcard_pcsc.c b/winpr/libwinpr/smartcard/smartcard_pcsc.c index 8d91c295e..38d013f31 100644 --- a/winpr/libwinpr/smartcard/smartcard_pcsc.c +++ b/winpr/libwinpr/smartcard/smartcard_pcsc.c @@ -707,7 +707,8 @@ char* PCSC_ConvertReaderNameToWinSCard(const char* name) */ if (!name) return NULL; - + memset(tokens, 0, sizeof(tokens)); + length = strlen(name); if (length < 10) @@ -753,7 +754,7 @@ char* PCSC_ConvertReaderNameToWinSCard(const char* name) if ((index < 0) || (slot < 0)) return NULL; - if (*(tokens[ctoken][1] - 1) == ')') + if (tokens[ctoken] && tokens[ctoken][1] && *(tokens[ctoken][1] - 1) == ')') { while ((*(tokens[ctoken][0]) != '(') && (ctoken > 0)) ctoken--; @@ -2358,7 +2359,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib_Internal(SCARDHANDLE hCard, DWORD dw WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib_FriendlyName(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr, LPDWORD pcbAttrLen) { int length = 0; - char* namePCSC; + char* namePCSC = NULL; char* nameWinSCard; DWORD cbAttrLen = 0; char* pbAttrA = NULL; @@ -2414,6 +2415,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib_FriendlyName(SCARDHANDLE hCard, DWOR else { friendlyNameA = namePCSC; + namePCSC = NULL; } if (dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_W) From 813e75e14d54618718fac85c7c62b2afed434420 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Thu, 16 Apr 2015 22:04:38 +0200 Subject: [PATCH 4/7] Fixed NULL dereference. --- winpr/libwinpr/utils/ini.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/winpr/libwinpr/utils/ini.c b/winpr/libwinpr/utils/ini.c index b7dd357ca..f46e41d7b 100644 --- a/winpr/libwinpr/utils/ini.c +++ b/winpr/libwinpr/utils/ini.c @@ -377,7 +377,7 @@ int IniFile_Load(wIniFile* ini) IniFile_AddKey(ini, section, name, value); key = NULL; - if (section->keys) + if (section && section->keys) key = section->keys[section->nKeys - 1]; } } From e5cdd8a29910030f9d07b75b636ddcadc1a6feef Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Sun, 19 Apr 2015 12:29:17 +0200 Subject: [PATCH 5/7] Fixed bitmap reading bug. --- winpr/libwinpr/utils/image.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/winpr/libwinpr/utils/image.c b/winpr/libwinpr/utils/image.c index 62b2cb0e1..f373e68f2 100644 --- a/winpr/libwinpr/utils/image.c +++ b/winpr/libwinpr/utils/image.c @@ -192,7 +192,7 @@ int winpr_image_bitmap_read_fp(wImage* image, FILE* fp) image->bitsPerPixel = bi.biBitCount; image->bytesPerPixel = (image->bitsPerPixel / 8); - image->scanline = (bi.biSizeImage / bi.biHeight); + image->scanline = (bi.biSizeImage / image->height); image->data = (BYTE*) malloc(bi.biSizeImage); From 7990ea6371f208ce0538e5002f2f3b7bcd024caf Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Sun, 19 Apr 2015 12:29:28 +0200 Subject: [PATCH 6/7] Added proper bitmap and png image test. --- winpr/libwinpr/utils/test/CMakeLists.txt | 2 + winpr/libwinpr/utils/test/TestImage.c | 231 +++++++++++++++++++- winpr/libwinpr/utils/test/lodepng_32bit.bmp | Bin 0 -> 16522 bytes winpr/libwinpr/utils/test/lodepng_32bit.png | Bin 0 -> 3968 bytes 4 files changed, 222 insertions(+), 11 deletions(-) create mode 100644 winpr/libwinpr/utils/test/lodepng_32bit.bmp create mode 100644 winpr/libwinpr/utils/test/lodepng_32bit.png diff --git a/winpr/libwinpr/utils/test/CMakeLists.txt b/winpr/libwinpr/utils/test/CMakeLists.txt index 134015ce2..02ec09aeb 100644 --- a/winpr/libwinpr/utils/test/CMakeLists.txt +++ b/winpr/libwinpr/utils/test/CMakeLists.txt @@ -31,6 +31,8 @@ create_test_sourcelist(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_DRIVER} ${${MODULE_PREFIX}_TESTS}) +add_definitions(-DTEST_SOURCE_PATH="${CMAKE_CURRENT_SOURCE_DIR}") + add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) target_link_libraries(${MODULE_NAME} winpr) diff --git a/winpr/libwinpr/utils/test/TestImage.c b/winpr/libwinpr/utils/test/TestImage.c index 72e8fc268..8bd66b513 100644 --- a/winpr/libwinpr/utils/test/TestImage.c +++ b/winpr/libwinpr/utils/test/TestImage.c @@ -3,38 +3,247 @@ #include #include #include +#include -int test_image_png_to_bmp() +#ifndef PATH_MAX +#define PATH_MAX 4096 +#endif + +static void *read_image(const char *src, size_t *size) +{ + int success = 0; + void *a = NULL; + long src_size; + FILE *fsrc = fopen(src, "r"); + + if (!fsrc) + goto cleanup; + + if (fseek(fsrc, 0, SEEK_END)) + goto cleanup; + + src_size = ftell(fsrc); + + if (fseek(fsrc, 0, SEEK_SET)) + goto cleanup; + + a = malloc(src_size); + + if (!a) + goto cleanup; + + if (fread(a, sizeof(char), src_size, fsrc) != src_size) + goto cleanup; + + success = 1; + *size = src_size; + +cleanup: + if (a && !success) + { + free(a); + a = NULL; + } + if (fsrc) + fclose(fsrc); + + return a; +} + + +static int compare(const char *src, const char *dst) +{ + int cmp = -1; + size_t asize, bsize; + void *a, *b; + + a = read_image(src, &asize); + b = read_image(dst, &bsize); + + if (!a || !b || (asize != bsize)) + goto cleanup; + + cmp = memcmp(a, b, asize); + +cleanup: + if (a) + free(a); + if (b) + free(b); + + return cmp; +} + +static int img_compare(wImage *image, wImage *image2) +{ + int rc = -1; + if (image->type != image2->type) + goto cleanup; + + if (image->width != image2->width) + goto cleanup; + + if (image->height != image2->height) + goto cleanup; + + if (image->scanline != image2->scanline) + goto cleanup; + + if (image->bitsPerPixel != image2->bitsPerPixel) + goto cleanup; + + if (image->bytesPerPixel != image2->bytesPerPixel) + goto cleanup; + + rc = memcmp(image->data, image2->data, image->scanline * image->height); + +cleanup: + return rc; +} + +static wImage *get_image(const char *src) { int status; - wImage* image; - - if (!PathFileExistsA("/tmp/test.png")) - return 1; /* skip */ + wImage* image = NULL; image = winpr_image_new(); if (!image) - return -1; + goto cleanup; - status = winpr_image_read(image, "/tmp/test.png"); + status = winpr_image_read(image, src); if (status < 0) + { + winpr_image_free(image, TRUE); + image = NULL; + } + +cleanup: + + return image; +} + +static int create_test(const char *src, const char *dst_png, const char *dst_bmp) +{ + int rc = -1; + int ret = -1; + int status; + size_t bsize; + void *buffer = NULL; + wImage* image = NULL, *image2 = NULL, *image3 = NULL, *image4 = NULL; + + if (!PathFileExistsA(src)) return -1; + image = get_image(src); + + /* Read from file using image methods. */ + if (!image) + goto cleanup; + + /* Write different formats to tmp. */ image->type = WINPR_IMAGE_BITMAP; - status = winpr_image_write(image, "/tmp/test_out.bmp"); + status = winpr_image_write(image, dst_bmp); if (status < 0) - return -1; + goto cleanup; image->type = WINPR_IMAGE_PNG; - status = winpr_image_write(image, "/tmp/test_out.png"); + status = winpr_image_write(image, dst_png); if (status < 0) + goto cleanup; + + /* Read image from buffer, compare. */ + buffer = read_image(src, &bsize); + if (!buffer) + goto cleanup; + + image2 = winpr_image_new(); + + if (!image2) + goto cleanup; + + status = winpr_image_read_buffer(image2, buffer, bsize); + + if (status < 0) + goto cleanup; + + rc = img_compare(image, image2); + if (rc) + goto cleanup; + + image3 = get_image(dst_png); + if (!image3) + goto cleanup; + + rc = img_compare(image, image3); + if (rc) + goto cleanup; + + image4 = get_image(dst_bmp); + if (!image4) + goto cleanup; + + image->type = WINPR_IMAGE_BITMAP; + rc = img_compare(image, image4); + if (rc) + goto cleanup; + + ret = 0; +cleanup: + if (image) + winpr_image_free(image, TRUE); + if (image2) + winpr_image_free(image2, TRUE); + if (image3) + winpr_image_free(image3, TRUE); + if (image4) + winpr_image_free(image4, TRUE); + if (buffer) + free(buffer); + + return ret; +} + +int test_image_png_to_bmp() +{ + char *buffer = TEST_SOURCE_PATH; + char src_png[PATH_MAX]; + char src_bmp[PATH_MAX]; + char dst_png[PATH_MAX]; + char dst_bmp[PATH_MAX]; + char dst_png2[PATH_MAX]; + char dst_bmp2[PATH_MAX]; + char *tmp = GetKnownPath(KNOWN_PATH_TEMP); + + if (!tmp) return -1; - winpr_image_free(image, TRUE); + if (!buffer) + return -1; + + snprintf(src_png, sizeof(src_png), "%s/lodepng_32bit.png", buffer); + snprintf(src_bmp, sizeof(src_bmp), "%s/lodepng_32bit.bmp", buffer); + snprintf(dst_png, sizeof(dst_png), "%s/lodepng_32bit.png", tmp); + snprintf(dst_bmp, sizeof(dst_bmp), "%s/lodepng_32bit.bmp", tmp); + snprintf(dst_png2, sizeof(dst_png2), "%s/lodepng_32bit-2.png", tmp); + snprintf(dst_bmp2, sizeof(dst_bmp2), "%s/lodepng_32bit-2.bmp", tmp); + + if (create_test(src_png, dst_png, dst_bmp)) + return -1; + + if (create_test(src_bmp, dst_png2, dst_bmp2)) + return -1; + +#if 0 + if (compare(dst_png2, dst_png)) + return -1; + + if (compare(dst_bmp2, dst_bmp)) + return -1; +#endif return 1; } diff --git a/winpr/libwinpr/utils/test/lodepng_32bit.bmp b/winpr/libwinpr/utils/test/lodepng_32bit.bmp new file mode 100644 index 0000000000000000000000000000000000000000..d52d34c0c23037b8408a57c697fe635cce05eaf0 GIT binary patch literal 16522 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 NcJ(~W`xiPA|1Z*JV7>qV literal 0 HcmV?d00001 diff --git a/winpr/libwinpr/utils/test/lodepng_32bit.png b/winpr/libwinpr/utils/test/lodepng_32bit.png new file mode 100644 index 0000000000000000000000000000000000000000..9c55f28eaaa73b281f3a4b901929212e4f57fd16 GIT binary patch literal 3968 zcmV-`4}b89P)00009a7bBm000XU z000XU0RWnu7ytkO2XskIMF-ym69_XFmOR@s0000PbVXQnLvL+uWo~o;Lvm$dbY)~9 zcWHEJAV*0}P*;Ht7XSbb`bk7VRA}DCT3wGN$x%HgBD3n=o;BE(5g^MT8424MUii1X z@Si{kYyp-RBiOZfx2I>iZ+&ED93Han$8_KBnb}>Nt5T>`bu05kWMst2$mBn~`N!Y3 zFK*-Zb=*xc-Roh|I%{r-Su?>^D}kb#n5t@G5@a9%!h|?U000OI0u&H{swyZTAp#*t z5`g|T5JxEhm#<#<3F^HNO#i(8%NOm-+qk=r`$=<$-cUmkkd7AsNC10BC%7lXCwc1Q zBs;i}h%+=@pwzpFPpv(Le(I%bE-3x7{QFn&`VfazYefr$6qjarrlGh5eN}^K4#I0TfDDyqW^s)1FFq2aLN;20J3S#~CW9xs!@B|i5|e>h zDItwY1M^tj!^UFPlvc4+uZm^ys#s)m#2hx4m=?~f=7nobf8Tz3U*DFt2%_MYM%xW( zcf3W}*x#pK z(sYf{B=a86O5R zO`0KM3x->4G?+0bxMLicl5#?Fkf)F@iDakBh(M_-1xwL1qZHjgpf){Bs#OmYTI;@n zrKmNuw$bnigoGnMjw6-OKmAg7Z{zmOW|-tC6+^~aFl4j_cSOJ)wZaT7;757Xfo_}m zlfw<}XAMb6Aki8~)CyA50ziie5t?R%FfWQgDMzfK4QQPB!)Y*&PXr*fU;RdRZ#6I5 zxO5|#ZM~i|=23>un0mfP_a)LD#(uvguKu?W>?lhGsZt?r)@|3|#uIj(RqYKu?ifg{zO?#p$u_-_QDWT|UCp=lY}jtKdEy?lpU*Gl$i;w;p&-$&c#d zU7#1C59bI0B<8Fhr>+k1A9QK+1n~*08F8euor|~uWKN0Sc?CeVqP2~me?uLfn

M zoO4W*;J(2%gApmwd!lsa+%qP}40G;=WPkdD$O#Vzl#1HU$>L>jmmYZ;KzhyPa>S)A zD4SjP1Tz2|NhOgJ%(xq1#&JMO+>OYY`yI!OapZ15&fJX{2M#&;PkziVZuPq_wXAwL z0N`3ds0H2Bg1!4wLcN^vBoyZW)!G)qPxYjyahdNfZ;}J#egw(=4(`0!!4p5Zfg3-0 zg(36RjmD8TdyFG*b{a+-bBsI7sSRWDpZ~Re^*TQPLes1__lVHE&|S;IVbHoFXOxQM zs10stt#i^%cEqiz1$yRhp^#dfNAi@&+yOCX02nez?njvOlN*@vlUM9;cO!0YVz+P<~-%do<2ir zLPV5?Qd@0NTB~3!O{NwNh6vFCFgc{no83207&2b%IgEI<$GFqYzNQho-GZT|ag9_{ zE=rZThQ;hHC|VOESSr|l^S_#AJsdQz9lh2Hpi{Taks?Sc1f#0prW#?^Dq2-3iqgsw zZEbCBwWyU=ROa9vR< zYefqv&=YS2YDJ3ge_y4xsS1j@KvGCT&pwI>m_i_<2Ef`NVO`Mz^TJwUURdTfc@%4_ zp<1j|MXW@t2tx}9grF_dI0RH@Bf_;9+(ip|1gfm8sKIGMZI~z3rg@TtWdRNADkIhv z?pRl(`z5WbuglOH$`S##5+KzgU}{l=2sN=)0bJLJ;B<&mc{pfYF&(rPO@}C}mRYrE zSrDOGQ7T&PHX$}r4H~t%C1`zdMg>Bs6_VB>1$raPf(WduNR;*L!Vv-x4e7Jb^!9B$ z-0Lu5SyYQ!Q+MxLLqcnP5vkVDs!G+mYF)IhnkJQ1(}dcz%!vuq*&j%l1|DN|PQZiAVY45nYO7gotxlerx2p1e<>GZ}qd!;`OZ_ z9&|YLjI4HC8f=lhiA1R|+s3g}LC49|`jpaTh*Er9PJb_ney*wX%U`t5KaaaREwk3L z4cv*JZ)xhHiKjrXa>@_q6PM7x28l_Z{tz9>a+dU#M3VZbavS3{mjmHJa zRu42IfsF{~ZA>NXM$qu;hA@0`Lm9qvLrdK6V9qg%&YXLHGNTb@r0KNJq-##t^&Cg0 zgx!wAz;VQoIgavVIf>3h$(RfhY%vm*iHHmY`(FbFgQjeTP$J5oY&n^tY~CkMr#XbM!IcE$tPCK;!iE?5O4i;&1FWU>m0sA49nkQhx!Y)vrY zERSvCXzV@#yhpJ<2p3h?e)X=az~dskh)(rptB{!ZtHoc3O`%zclL8m@~79Cqy^EFC zpr7FOa~LLAY;XbO3U5disbMIvfCngeK>b^ar|jDI?ujsnXolu!L`x7+()KC{@Ivzd zkoaB4Boy^X|Ja?nAukb|Kp+JWaKS2)-~}l(6qt}#lVoU|5kFQiTcBsZ9dl zsklu95so0LqZw*Kb2LZz_5_Yf;JAaz24nIcCfzqJLXo293qe8>LKp%ej12(}O>D@3 zH4F`?7%Qw|x5^8~!n|TA@D;f#6$}NrtFgcXUIEG*M0i6SPq~~<3N{0X=0~d=OG0!V z5}E^q2-ud?CFDryXC7}uB``NB6oNHC$Q1|x`ii_N ztw^fB`FDh!qsrfB+i+QP-2| zWx(OF0<4W=sNcxWY)MBp%K(`0mtU|xDDI^NScDZ;!~j>YV_L-uR#*`#*uW+hpvwT7 z&^E075HaI|d3AG#G*;QDb%D&9zw(13<_4w9cPz6gT&109;ZqF##lQaVWWd858>@_keEPhIFE ae*Xu4^#Q~twaCW+0000 Date: Mon, 20 Apr 2015 15:13:23 +0200 Subject: [PATCH 7/7] Fixed reading bitmap from buffer. --- winpr/libwinpr/utils/image.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/winpr/libwinpr/utils/image.c b/winpr/libwinpr/utils/image.c index f373e68f2..d6c5a0f6e 100644 --- a/winpr/libwinpr/utils/image.c +++ b/winpr/libwinpr/utils/image.c @@ -261,7 +261,7 @@ int winpr_image_bitmap_read_buffer(wImage* image, BYTE* buffer, int size) image->bitsPerPixel = bi.biBitCount; image->bytesPerPixel = (image->bitsPerPixel / 8); - image->scanline = (bi.biSizeImage / bi.biHeight); + image->scanline = (bi.biSizeImage / image->height); image->data = (BYTE*) malloc(bi.biSizeImage);