From d4c41fe0dabe2d1539763c899f879cc1e391750a Mon Sep 17 00:00:00 2001 From: DRC Date: Sat, 18 Mar 2017 12:56:36 -0500 Subject: [PATCH 1/9] TurboJPEG: Fix potential memory leaks Referring to https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=746, it seems that the values of local buffer pointers in TurboJPEG API functions aren't always preserved if longjmp() returns control to a point prior to the allocation of the local buffers. This is known to be an issue with GCC 4.x and clang with -O1 and higher optimization levels but not with GCC 5.x and later. It is unknown why GCC 5.x and 6.x do not suffer from the issue, but possibly the local buffer pointers are not allocated on the stack when using those more recent compilers. In any case, this commit modifies the TurboJPEG API library code such that the jump buffer is always updated after any local buffer pointers are allocated but before any subsequent libjpeg API functions are called. --- ChangeLog.md | 6 ++++ turbojpeg.c | 79 +++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 63 insertions(+), 22 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 47ebb70b..620c2f8e 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -38,6 +38,12 @@ API/ABI emulation, since the behavior is entirely internal. Note that `-copy all` must be passed to jpegtran in order to transfer the EXIF tags from the source image to the destination image. +8. Fixed several memory leaks in the TurboJPEG API library that could occur +if the library was built with certain compilers and optimization levels +(known to occur with GCC 4.x and clang with `-O1` and higher but not with +GCC 5.x or 6.x) and one of the underlying libjpeg API functions threw an error +after a TurboJPEG API function allocated a local buffer. + 1.5.1 ===== diff --git a/turbojpeg.c b/turbojpeg.c index 6533b411..c9bc6197 100644 --- a/turbojpeg.c +++ b/turbojpeg.c @@ -1,5 +1,5 @@ /* - * Copyright (C)2009-2016 D. R. Commander. All Rights Reserved. + * Copyright (C)2009-2017 D. R. Commander. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -772,13 +772,6 @@ DLLEXPORT int DLLCALL tjCompress2(tjhandle handle, const unsigned char *srcBuf, || jpegSubsamp<0 || jpegSubsamp>=NUMSUBOPT || jpegQual<0 || jpegQual>100) _throw("tjCompress2(): Invalid argument"); - if(setjmp(this->jerr.setjmp_buffer)) - { - /* If we get here, the JPEG code has signaled an error. */ - retval=-1; - goto bailout; - } - if(pitch==0) pitch=width*tjPixelSize[pixelFormat]; #ifndef JCS_EXTENSIONS @@ -791,6 +784,16 @@ DLLEXPORT int DLLCALL tjCompress2(tjhandle handle, const unsigned char *srcBuf, } #endif + if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*height))==NULL) + _throw("tjCompress2(): Memory allocation failure"); + + if(setjmp(this->jerr.setjmp_buffer)) + { + /* If we get here, the JPEG code has signaled an error. */ + retval=-1; + goto bailout; + } + cinfo->image_width=width; cinfo->image_height=height; @@ -807,8 +810,6 @@ DLLEXPORT int DLLCALL tjCompress2(tjhandle handle, const unsigned char *srcBuf, return -1; jpeg_start_compress(cinfo, TRUE); - if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*height))==NULL) - _throw("tjCompress2(): Memory allocation failure"); for(i=0; ijerr.setjmp_buffer)) - { - /* If we get here, the JPEG code has signaled an error. */ - retval=-1; - goto bailout; - } - if(pixelFormat==TJPF_CMYK) _throw("tjEncodeYUVPlanes(): Cannot generate YUV images from CMYK pixels"); @@ -910,6 +904,13 @@ DLLEXPORT int DLLCALL tjEncodeYUVPlanes(tjhandle handle, } #endif + if(setjmp(this->jerr.setjmp_buffer)) + { + /* If we get here, the JPEG code has signaled an error. */ + retval=-1; + goto bailout; + } + cinfo->image_width=width; cinfo->image_height=height; @@ -986,6 +987,13 @@ DLLEXPORT int DLLCALL tjEncodeYUVPlanes(tjhandle handle, } } + if(setjmp(this->jerr.setjmp_buffer)) + { + /* If we get here, the JPEG code has signaled an error. */ + retval=-1; + goto bailout; + } + for(row=0; rowmax_v_samp_factor) { (*cinfo->cconvert->color_convert)(cinfo, &row_pointer[row], tmpbuf, 0, @@ -1160,6 +1168,13 @@ DLLEXPORT int DLLCALL tjCompressFromYUVPlanes(tjhandle handle, } } + if(setjmp(this->jerr.setjmp_buffer)) + { + /* If we get here, the JPEG code has signaled an error. */ + retval=-1; + goto bailout; + } + for(row=0; row<(int)cinfo->image_height; row+=cinfo->max_v_samp_factor*DCTSIZE) { @@ -1438,6 +1453,12 @@ DLLEXPORT int DLLCALL tjDecompress2(tjhandle handle, if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW) *dinfo->output_height))==NULL) _throw("tjDecompress2(): Memory allocation failure"); + if(setjmp(this->jerr.setjmp_buffer)) + { + /* If we get here, the JPEG code has signaled an error. */ + retval=-1; + goto bailout; + } for(i=0; i<(int)dinfo->output_height; i++) { if(flags&TJFLAG_BOTTOMUP) @@ -1660,6 +1681,13 @@ DLLEXPORT int DLLCALL tjDecodeYUVPlanes(tjhandle handle, } } + if(setjmp(this->jerr.setjmp_buffer)) + { + /* If we get here, the JPEG code has signaled an error. */ + retval=-1; + goto bailout; + } + for(row=0; rowmax_v_samp_factor) { JDIMENSION inrow=0, outrow=0; @@ -1840,6 +1868,13 @@ DLLEXPORT int DLLCALL tjDecompressToYUVPlanes(tjhandle handle, } } + if(setjmp(this->jerr.setjmp_buffer)) + { + /* If we get here, the JPEG code has signaled an error. */ + retval=-1; + goto bailout; + } + if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE; if(flags&TJFLAG_FASTDCT) dinfo->dct_method=JDCT_FASTEST; dinfo->raw_data_out=TRUE; @@ -2017,6 +2052,11 @@ DLLEXPORT int DLLCALL tjTransform(tjhandle handle, else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1"); else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1"); + if((xinfo=(jpeg_transform_info *)malloc(sizeof(jpeg_transform_info)*n)) + ==NULL) + _throw("tjTransform(): Memory allocation failure"); + MEMZERO(xinfo, sizeof(jpeg_transform_info)*n); + if(setjmp(this->jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. */ @@ -2026,11 +2066,6 @@ DLLEXPORT int DLLCALL tjTransform(tjhandle handle, jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize); - if((xinfo=(jpeg_transform_info *)malloc(sizeof(jpeg_transform_info)*n)) - ==NULL) - _throw("tjTransform(): Memory allocation failure"); - MEMZERO(xinfo, sizeof(jpeg_transform_info)*n); - for(i=0; i Date: Sat, 18 Mar 2017 13:24:50 -0500 Subject: [PATCH 2/9] AppVeyor: Fix CI build Something changed in the CI build environment, and our previous trick of setting the Git URL to file://c:/projects/libjpeg-turbo no longer works. Using cygpath to translate the Windows path to a MinGW-friendly format is a better solution anyhow. --- appveyor.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 5b615ea0..4f2d6cc9 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -24,7 +24,9 @@ install: build_script: - cmd: >- - bash c:/buildscripts/buildljt -r file://%CD:\=/% -b /c/ljt.nightly %APPVEYOR_REPO_BRANCH% -v + for /f %%i in ('"cygpath %CD%"') do set MINGWPATH=%%i + + bash c:/buildscripts/buildljt -r file://%MINGWPATH% -b /c/ljt.nightly %APPVEYOR_REPO_BRANCH% -v move c:\ljt.nightly\files\*.tar.gz . From da2a27ef056a0179cbd80f9146e58b89403d9933 Mon Sep 17 00:00:00 2001 From: DRC Date: Sat, 18 Mar 2017 16:15:14 -0500 Subject: [PATCH 3/9] Honor max_memory_to_use/JPEGMEM/-maxmemory This re-introduces a feature of the obsolete system-specific libjpeg memory managers-- namely the ability to limit the amount of main memory used by the library during decompression or multi-pass compression. This is mainly beneficial for two reasons: - Works around a 2 GB limit in libFuzzer - Allows security-sensitive applications to set a memory limit for the JPEG decoder so as to work around the progressive JPEG exploit (LJT-01-004) described here: http://www.libjpeg-turbo.org/pmwiki/uploads/About/TwoIssueswiththeJPEGStandard.pdf This commit also removes obsolete documentation regarding the MS-DOS memory manager (which itself was removed long ago) and changes the documentation of the -maxmemory switch and JPEGMEM environment variable to reflect the fact that backing stores are never used in libjpeg-turbo. Inspired by: https://github.com/caolanm/libjpeg-turbo/commit/066fee2e7d6834f24838bc1896aa38ca77209e3c Closes #143 --- ChangeLog.md | 15 +++++++++++++++ cjpeg.1 | 4 ++-- djpeg.1 | 4 ++-- jmemnobs.c | 16 +++++++++++----- jpegtran.1 | 4 ++-- libjpeg.txt | 14 ++++++-------- structure.txt | 24 +++++++++++------------- usage.txt | 35 +++++------------------------------ 8 files changed, 54 insertions(+), 62 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 620c2f8e..07a6cf52 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -44,6 +44,21 @@ if the library was built with certain compilers and optimization levels GCC 5.x or 6.x) and one of the underlying libjpeg API functions threw an error after a TurboJPEG API function allocated a local buffer. +9. The libjpeg-turbo memory manager will now honor the `max_memory_to_use` +structure member in jpeg\_memory\_mgr, which can be set to the maximum amount +of memory (in bytes) that libjpeg-turbo should use during decompression or +multi-pass (including progressive) compression. This limit can also be set +using the `JPEGMEM` environment variable or using the `-maxmemory` switch in +cjpeg/djpeg/jpegtran (refer to the respective man pages for more details.) +This has been a documented feature of libjpeg since v5, but the +`malloc()`/`free()` implementation of the memory manager (jmemnobs.c) never +implemented the feature. Restricting libjpeg-turbo's memory usage is useful +for two reasons: it allows testers to more easily work around the 2 GB limit +in libFuzzer, and it allows developers of security-sensitive applications to +more easily defend against one of the progressive JPEG exploits (LJT-01-004) +identified in +[this report](http://www.libjpeg-turbo.org/pmwiki/uploads/About/TwoIssueswiththeJPEGStandard.pdf). + 1.5.1 ===== diff --git a/cjpeg.1 b/cjpeg.1 index d1dc3041..283fc81f 100644 --- a/cjpeg.1 +++ b/cjpeg.1 @@ -1,4 +1,4 @@ -.TH CJPEG 1 "17 February 2016" +.TH CJPEG 1 "18 March 2017" .SH NAME cjpeg \- compress an image file to a JPEG file .SH SYNOPSIS @@ -202,7 +202,7 @@ Set limit for amount of memory to use in processing large images. Value is in thousands of bytes, or millions of bytes if "M" is attached to the number. For example, .B \-max 4m -selects 4000000 bytes. If more space is needed, temporary files will be used. +selects 4000000 bytes. If more space is needed, an error will occur. .TP .BI \-outfile " name" Send output image to the named file, not to standard output. diff --git a/djpeg.1 b/djpeg.1 index 7efde43b..b1e7f76e 100644 --- a/djpeg.1 +++ b/djpeg.1 @@ -1,4 +1,4 @@ -.TH DJPEG 1 "18 February 2016" +.TH DJPEG 1 "18 March 2017" .SH NAME djpeg \- decompress a JPEG file to an image file .SH SYNOPSIS @@ -185,7 +185,7 @@ Set limit for amount of memory to use in processing large images. Value is in thousands of bytes, or millions of bytes if "M" is attached to the number. For example, .B \-max 4m -selects 4000000 bytes. If more space is needed, temporary files will be used. +selects 4000000 bytes. If more space is needed, an error will occur. .TP .BI \-outfile " name" Send output image to the named file, not to standard output. diff --git a/jmemnobs.c b/jmemnobs.c index 5797198d..ac12afa5 100644 --- a/jmemnobs.c +++ b/jmemnobs.c @@ -3,8 +3,8 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1992-1996, Thomas G. Lane. - * It was modified by The libjpeg-turbo Project to include only code and - * information relevant to libjpeg-turbo. + * libjpeg-turbo Modifications: + * Copyright (C) 2017, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -15,7 +15,6 @@ * This is very portable in the sense that it'll compile on almost anything, * but you'd better have lots of main memory (or virtual memory) if you want * to process big images. - * Note that the max_memory_to_use option is ignored by this implementation. */ #define JPEG_INTERNALS @@ -66,14 +65,21 @@ jpeg_free_large (j_common_ptr cinfo, void *object, size_t sizeofobject) /* * This routine computes the total memory space available for allocation. - * Here we always say, "we got all you want bud!" */ GLOBAL(size_t) jpeg_mem_available (j_common_ptr cinfo, size_t min_bytes_needed, size_t max_bytes_needed, size_t already_allocated) { - return max_bytes_needed; + if (cinfo->mem->max_memory_to_use) { + if (cinfo->mem->max_memory_to_use > already_allocated) + return cinfo->mem->max_memory_to_use - already_allocated; + else + return 0; + } else { + /* Here we always say, "we got all you want bud!" */ + return max_bytes_needed; + } } diff --git a/jpegtran.1 b/jpegtran.1 index 7f3c8531..631455b6 100644 --- a/jpegtran.1 +++ b/jpegtran.1 @@ -1,4 +1,4 @@ -.TH JPEGTRAN 1 "18 February 2016" +.TH JPEGTRAN 1 "18 March 2017" .SH NAME jpegtran \- lossless transformation of JPEG files .SH SYNOPSIS @@ -222,7 +222,7 @@ Set limit for amount of memory to use in processing large images. Value is in thousands of bytes, or millions of bytes if "M" is attached to the number. For example, .B \-max 4m -selects 4000000 bytes. If more space is needed, temporary files will be used. +selects 4000000 bytes. If more space is needed, an error will occur. .TP .BI \-outfile " name" Send output image to the named file, not to standard output. diff --git a/libjpeg.txt b/libjpeg.txt index 2aa10278..5181afc0 100644 --- a/libjpeg.txt +++ b/libjpeg.txt @@ -3,7 +3,7 @@ USING THE IJG JPEG LIBRARY This file was part of the Independent JPEG Group's software: Copyright (C) 1994-2013, Thomas G. Lane, Guido Vollbeding. libjpeg-turbo Modifications: -Copyright (C) 2010, 2014-2016, D. R. Commander. +Copyright (C) 2010, 2014-2017, D. R. Commander. Copyright (C) 2015, Google, Inc. For conditions of distribution and use, see the accompanying README.ijg file. @@ -2942,13 +2942,6 @@ Some operating modes (eg, two-pass color quantization) require full-image buffers. Such buffers are treated as "virtual arrays": only the current strip need be in memory, and the rest can be swapped out to a temporary file. -If you use the simplest memory manager back end (jmemnobs.c), then no -temporary files are used; virtual arrays are simply malloc()'d. Images bigger -than memory can be processed only if your system supports virtual memory. -The other memory manager back ends support temporary files of various flavors -and thus work in machines without virtual memory. They may also be useful on -Unix machines if you need to process images that exceed available swap space. - When using temporary files, the library will make the in-memory buffers for its virtual arrays just big enough to stay within a "maximum memory" setting. Your application can set this limit by setting cinfo->mem->max_memory_to_use @@ -2961,6 +2954,11 @@ that space allocated with alloc_small() is ignored, on the assumption that it's too small to be worth worrying about; so a reasonable safety margin should be left when setting max_memory_to_use. +NOTE: Unless you develop your own memory manager back end, then temporary files +will never be used. The back end provided in libjpeg-turbo (jmemnobs.c) simply +malloc()s and free()s virtual arrays, and an error occurs if the required +memory exceeds the limit specified in cinfo->mem->max_memory_to_use. + Memory usage ------------ diff --git a/structure.txt b/structure.txt index 296d1250..f69c9d87 100644 --- a/structure.txt +++ b/structure.txt @@ -832,21 +832,19 @@ read_backing_store, manipulate a backing-store object write_backing_store, close_backing_store -On some systems there will be more than one type of backing-store object -(specifically, in MS-DOS a backing store file might be an area of extended -memory as well as a disk file). jpeg_open_backing_store is responsible for -choosing how to implement a given object. The read/write/close routines -are method pointers in the structure that describes a given object; this -lets them be different for different object types. +On some systems there will be more than one type of backing-store object. +jpeg_open_backing_store is responsible for choosing how to implement a given +object. The read/write/close routines are method pointers in the structure +that describes a given object; this lets them be different for different object +types. It may be necessary to ensure that backing store objects are explicitly -released upon abnormal program termination. For example, MS-DOS won't free -extended memory by itself. To support this, we will expect the main program -or surrounding application to arrange to call self_destruct (typically via -jpeg_destroy) upon abnormal termination. This may require a SIGINT signal -handler or equivalent. We don't want to have the back end module install its -own signal handler, because that would pre-empt the surrounding application's -ability to control signal handling. +released upon abnormal program termination. To support this, we will expect +the main program or surrounding application to arrange to call self_destruct +(typically via jpeg_destroy) upon abnormal termination. This may require a +SIGINT signal handler or equivalent. We don't want to have the back end module +install its own signal handler, because that would pre-empt the surrounding +application's ability to control signal handling. The IJG distribution includes several memory manager back end implementations. Usually the same back end should be suitable for all applications on a given diff --git a/usage.txt b/usage.txt index 5abda4ed..ed97aa98 100644 --- a/usage.txt +++ b/usage.txt @@ -212,7 +212,7 @@ Switches for advanced users: large images. Value is in thousands of bytes, or millions of bytes if "M" is attached to the number. For example, -max 4m selects 4000000 bytes. If more - space is needed, temporary files will be used. + space is needed, an error will occur. -verbose Enable debug printout. More -v's give more printout. or -debug Also, version information is printed at startup. @@ -377,7 +377,7 @@ Switches for advanced users: large images. Value is in thousands of bytes, or millions of bytes if "M" is attached to the number. For example, -max 4m selects 4000000 bytes. If more - space is needed, temporary files will be used. + space is needed, an error will occur. -verbose Enable debug printout. More -v's give more printout. or -debug Also, version information is printed at startup. @@ -423,11 +423,6 @@ When producing a color-quantized image, "-onepass -dither ordered" is fast but much lower quality than the default behavior. "-dither none" may give acceptable results in two-pass mode, but is seldom tolerable in one-pass mode. -Two-pass color quantization requires a good deal of memory; on MS-DOS machines -it may run out of memory even with -maxmemory 0. In that case you can still -decompress, with some loss of image quality, by specifying -onepass for -one-pass quantization. - To avoid the Unisys LZW patent (now expired), djpeg produces uncompressed GIF files. These are larger than they should be, but are readable by standard GIF decoders. @@ -435,24 +430,9 @@ decoders. HINTS FOR BOTH PROGRAMS -If more space is needed than will fit in the available main memory (as -determined by -maxmemory), temporary files will be used. (MS-DOS versions -will try to get extended or expanded memory first.) The temporary files are -often rather large: in typical cases they occupy three bytes per pixel, for -example 3*800*600 = 1.44Mb for an 800x600 image. If you don't have enough -free disk space, leave out -progressive and -optimize (for cjpeg) or specify --onepass (for djpeg). - -On MS-DOS, the temporary files are created in the directory named by the TMP -or TEMP environment variable, or in the current directory if neither of those -exist. Amiga implementations put the temp files in the directory named by -JPEGTMP:, so be sure to assign JPEGTMP: to a disk partition with adequate free -space. - -The default memory usage limit (-maxmemory) is set when the software is -compiled. If you get an "insufficient memory" error, try specifying a smaller --maxmemory value, even -maxmemory 0 to use the absolute minimum space. You -may want to recompile with a smaller default value if this happens often. +If the memory needed by cjpeg or djpeg exceeds the limit specified by +-maxmemory, an error will occur. You can leave out -progressive and -optimize +(for cjpeg) or specify -onepass (for djpeg) to reduce memory usage. On machines that have "environment" variables, you can define the environment variable JPEGMEM to set the default memory limit. The value is specified as @@ -460,11 +440,6 @@ described for the -maxmemory switch. JPEGMEM overrides the default value specified when the program was compiled, and itself is overridden by an explicit -maxmemory switch. -On MS-DOS machines, -maxmemory is the amount of main (conventional) memory to -use. (Extended or expanded memory is also used if available.) Most -DOS-specific versions of this software do their own memory space estimation -and do not need you to specify -maxmemory. - JPEGTRAN From 9d64f3c60b43507d4baf4f669ce2b27f2649c78b Mon Sep 17 00:00:00 2001 From: DRC Date: Mon, 24 Apr 2017 14:42:58 -0500 Subject: [PATCH 4/9] Attribute ARM runtime detection code to Nokia This code was submitted in the initial ARM NEON patches (https://sourceforge.net/p/libjpeg-turbo/patches/7/) by Siarhei while he was still a Nokia employee. --- simd/jsimd_arm.c | 1 + simd/jsimd_arm64.c | 1 + 2 files changed, 2 insertions(+) diff --git a/simd/jsimd_arm.c b/simd/jsimd_arm.c index 61cd073e..0b955cdd 100644 --- a/simd/jsimd_arm.c +++ b/simd/jsimd_arm.c @@ -2,6 +2,7 @@ * jsimd_arm.c * * Copyright 2009 Pierre Ossman for Cendio AB + * Copyright (C) 2011, Nokia Corporation and/or its subsidiary(-ies). * Copyright (C) 2009-2011, 2013-2014, 2016, D. R. Commander. * Copyright (C) 2015-2016, Matthieu Darbois. * diff --git a/simd/jsimd_arm64.c b/simd/jsimd_arm64.c index 09449bb6..f6e97364 100644 --- a/simd/jsimd_arm64.c +++ b/simd/jsimd_arm64.c @@ -2,6 +2,7 @@ * jsimd_arm64.c * * Copyright 2009 Pierre Ossman for Cendio AB + * Copyright (C) 2011, Nokia Corporation and/or its subsidiary(-ies). * Copyright (C) 2009-2011, 2013-2014, 2016, D. R. Commander. * Copyright (C) 2015-2016, Matthieu Darbois. * From 2a4f189444b9382f6ed3e8007f84676531b650b2 Mon Sep 17 00:00:00 2001 From: DRC Date: Fri, 5 May 2017 20:45:40 -0500 Subject: [PATCH 5/9] Restore compatibility with older autoconf releases (broken by f06cc1200fd5f61b63479d7099ccf4a7457a89bd) Fixes #149 --- configure.ac | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 05428811..5766b878 100644 --- a/configure.ac +++ b/configure.ac @@ -225,9 +225,9 @@ AC_SUBST(MEM_SRCDST_FUNCTIONS) AC_DEFINE_UNQUOTED(LIBJPEG_TURBO_VERSION, [$VERSION], [libjpeg-turbo version]) m4_define(version_triplet,m4_split(AC_PACKAGE_VERSION,[[.]])) -m4_define(version_major,m4_argn(1,version_triplet)) -m4_define(version_minor,m4_argn(2,version_triplet)) -m4_define(version_revision,m4_argn(3,version_triplet)) +m4_define(version_major,m4_car(m4_shiftn(1,[],version_triplet))) +m4_define(version_minor,m4_car(m4_shiftn(2,[],version_triplet))) +m4_define(version_revision,m4_car(m4_shiftn(3,[],version_triplet))) VERSION_MAJOR=version_major VERSION_MINOR=version_minor VERSION_REVISION=version_revision From 70f236ddd7d379eb0077bce7763132fba4983dcd Mon Sep 17 00:00:00 2001 From: DRC Date: Mon, 8 May 2017 08:15:11 -0500 Subject: [PATCH 6/9] Travis: Fix OS X build The Travis xcode7.3 image now apparently includes GnuPG 1.4.x by default, so use it instead of installing GnuPG 2. Using GnuPG 2.1.x, the default version in Homebrew as of this writing, is problematic for this reason: https://wiki.archlinux.org/index.php/GnuPG#Unattended_passphrase --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 53ded2b9..c1e36bdc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -43,7 +43,8 @@ matrix: before_install: - if [ "$TRAVIS_OS_NAME" = "osx" ]; then - brew install nasm homebrew/versions/gcc5 md5sha1sum Caskroom/versions/java6 gpg && + brew install nasm homebrew/versions/gcc5 md5sha1sum Caskroom/versions/java6 && + ln -fs /usr/local/bin/gpg1 /usr/local/bin/gpg && git clone --depth=1 https://github.com/libjpeg-turbo/gas-preprocessor.git ~/src/gas-preprocessor && ln -fs /Applications/Xcode.app /Applications/Xcode72.app; fi From 301ba4f305a5a9b30af856553603847ea69f0e73 Mon Sep 17 00:00:00 2001 From: DRC Date: Mon, 26 Jun 2017 15:15:08 -0500 Subject: [PATCH 7/9] BUILDING.md: Include Android/x86 build recipes Addresses a concern raised in #155. --- BUILDING.md | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/BUILDING.md b/BUILDING.md index 9d05f0ba..2725f30a 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -442,6 +442,79 @@ needs. LDFLAGS="${ANDROID_CFLAGS} -pie" --with-simd ${1+"$@"} make + +### x86 (32-bit) + +The following is a general recipe script that can be modified for your specific +needs. + + # Set these variables to suit your needs + NDK_PATH={full path to the "ndk" directory-- for example, /opt/android/sdk/ndk-bundle} + BUILD_PLATFORM={the platform name for the NDK package you installed-- + for example, "windows-x86" or "linux-x86_64" or "darwin-x86_64"} + TOOLCHAIN_VERSION={"4.8", "4.9", "clang3.5", etc. This corresponds to a + toolchain directory under ${NDK_PATH}/toolchains/.} + ANDROID_VERSION={The minimum version of Android to support-- for example, + "16", "19", etc.} + + # It should not be necessary to modify the rest + HOST=i686-linux-android + SYSROOT=${NDK_PATH}/platforms/android-${ANDROID_VERSION}/arch-x86 + ANDROID_CFLAGS="--sysroot=${SYSROOT}" + + TOOLCHAIN=${NDK_PATH}/toolchains/x86-${TOOLCHAIN_VERSION}/prebuilt/${BUILD_PLATFORM} + export CPP=${TOOLCHAIN}/bin/${HOST}-cpp + export AR=${TOOLCHAIN}/bin/${HOST}-ar + export NM=${TOOLCHAIN}/bin/${HOST}-nm + export CC=${TOOLCHAIN}/bin/${HOST}-gcc + export LD=${TOOLCHAIN}/bin/${HOST}-ld + export RANLIB=${TOOLCHAIN}/bin/${HOST}-ranlib + export OBJDUMP=${TOOLCHAIN}/bin/${HOST}-objdump + export STRIP=${TOOLCHAIN}/bin/${HOST}-strip + cd {build_directory} + sh {source_directory}/configure --host=${HOST} \ + CFLAGS="${ANDROID_CFLAGS} -O3 -fPIE" \ + CPPFLAGS="${ANDROID_CFLAGS}" \ + LDFLAGS="${ANDROID_CFLAGS} -pie" --with-simd ${1+"$@"} + make + + +### x86-64 (64-bit) + +The following is a general recipe script that can be modified for your specific +needs. + + # Set these variables to suit your needs + NDK_PATH={full path to the "ndk" directory-- for example, /opt/android/sdk/ndk-bundle} + BUILD_PLATFORM={the platform name for the NDK package you installed-- + for example, "windows-x86" or "linux-x86_64" or "darwin-x86_64"} + TOOLCHAIN_VERSION={"4.8", "4.9", "clang3.5", etc. This corresponds to a + toolchain directory under ${NDK_PATH}/toolchains/.} + ANDROID_VERSION={The minimum version of Android to support. "21" or later + is required for a 64-bit build.} + + # It should not be necessary to modify the rest + HOST=x86_64-linux-android + SYSROOT=${NDK_PATH}/platforms/android-${ANDROID_VERSION}/arch-x86_64 + ANDROID_CFLAGS="--sysroot=${SYSROOT}" + + TOOLCHAIN=${NDK_PATH}/toolchains/x86_64-${TOOLCHAIN_VERSION}/prebuilt/${BUILD_PLATFORM} + export CPP=${TOOLCHAIN}/bin/${HOST}-cpp + export AR=${TOOLCHAIN}/bin/${HOST}-ar + export NM=${TOOLCHAIN}/bin/${HOST}-nm + export CC=${TOOLCHAIN}/bin/${HOST}-gcc + export LD=${TOOLCHAIN}/bin/${HOST}-ld + export RANLIB=${TOOLCHAIN}/bin/${HOST}-ranlib + export OBJDUMP=${TOOLCHAIN}/bin/${HOST}-objdump + export STRIP=${TOOLCHAIN}/bin/${HOST}-strip + cd {build_directory} + sh {source_directory}/configure --host=${HOST} \ + CFLAGS="${ANDROID_CFLAGS} -O3 -fPIE" \ + CPPFLAGS="${ANDROID_CFLAGS}" \ + LDFLAGS="${ANDROID_CFLAGS} -pie" --with-simd ${1+"$@"} + make + + If building for Android 4.0.x (API level < 16) or earlier, remove `-fPIE` from `CFLAGS` and `-pie` from `LDFLAGS`. From 11eec4a398f3fc1b9d39c1d3b81b53ae85d9b5e6 Mon Sep 17 00:00:00 2001 From: DRC Date: Mon, 26 Jun 2017 20:48:02 -0500 Subject: [PATCH 8/9] TJBench: Fix errors when decomp. files w/ ICC data Embedded ICC profiles can cause the size of a JPEG file to exceed the size returned by tjBufSize() (which is really meant to be used for compression anyhow, not for decompression), and this was causing a segfault (C) or an ArrayIndexOutOfBoundsException (Java) when decompressing such files with TJBench. This commit modifies the benchmark such that, when tiled decompression is disabled, it re-uses the source buffer as the primary JPEG buffer. --- java/TJBench.java | 4 ++-- tjbench.c | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/java/TJBench.java b/java/TJBench.java index 23fab612..618cc977 100644 --- a/java/TJBench.java +++ b/java/TJBench.java @@ -1,5 +1,5 @@ /* - * Copyright (C)2009-2014, 2016 D. R. Commander. All Rights Reserved. + * Copyright (C)2009-2014, 2016-2017 D. R. Commander. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -582,8 +582,8 @@ class TJBench { System.out.print("N/A N/A "); jpegBuf = new byte[1][TJ.bufSize(_tilew, _tileh, subsamp)]; jpegSize = new int[1]; + jpegBuf[0] = srcBuf; jpegSize[0] = srcSize; - System.arraycopy(srcBuf, 0, jpegBuf[0], 0, srcSize); } if (w == tilew) diff --git a/tjbench.c b/tjbench.c index 9db1968c..626788b7 100644 --- a/tjbench.c +++ b/tjbench.c @@ -1,5 +1,5 @@ /* - * Copyright (C)2009-2016 D. R. Commander. All Rights Reserved. + * Copyright (C)2009-2017 D. R. Commander. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -668,7 +668,9 @@ int decompTest(char *filename) { if(quiet==1) printf("N/A N/A "); jpegsize[0]=srcsize; - memcpy(jpegbuf[0], srcbuf, srcsize); + free(jpegbuf[0]); + jpegbuf[0]=srcbuf; + srcbuf=NULL; } if(w==tilew) _tilew=_w; From 6a2b06742818e7d505738f35b9b589a958f98f0a Mon Sep 17 00:00:00 2001 From: DRC Date: Thu, 11 May 2017 18:33:47 -0500 Subject: [PATCH 9/9] TJBench: Code formatting tweaks Spaces-->tab + remove stray control character that was introduced in 95e4cb206085c3a715f0f017c174fdf367a2c1ff --- tjbench.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tjbench.c b/tjbench.c index 626788b7..12b4efe5 100644 --- a/tjbench.c +++ b/tjbench.c @@ -40,7 +40,7 @@ #define _throw(op, err) { \ printf("ERROR in line %d while %s:\n%s\n", __LINE__, op, err); \ - retval=-1; goto bailout;} + retval=-1; goto bailout;} #define _throwunix(m) _throw(m, strerror(errno)) #define _throwtj(m) _throw(m, tjGetErrorStr()) #define _throwbmp(m) _throw(m, bmpgeterr()) @@ -207,7 +207,7 @@ int decomp(unsigned char *srcbuf, unsigned char **jpegbuf, (double)(w*h)/1000000.*(double)iter/elapsed); if(doyuv) { - printf("YUV Decode --> Frame rate:  %f fps\n", + printf("YUV Decode --> Frame rate: %f fps\n", (double)iter/elapsedDecode); printf(" Throughput: %f Megapixels/sec\n", (double)(w*h)/1000000.*(double)iter/elapsedDecode);