Giter VIP home page Giter VIP logo

demoiccmax's Introduction

Demo ICC Max Logo

DemoIccMAX

Introduction

The DemoIccMAX project (formally known as RefIccMAX) provides an open source set of libraries and tools that allow for the interaction, manipulation, and application of iccMAX based color management profiles based on the iccMAX profile specification in addition to legacy ICC profiles defined by earlier ICC profile specifications.

iccMAX is not intended as a replacement for legacy ICC.1 based profiles, the existing architecture, but as an extension or alternative where requirements cannot be fully met by ICC.1. Some of the areas covered by iccMAX include: Multi-spectral, Medical Imaging, Image Capture/Digital Photography, Package Printing, Color Management on Internet, Fine Art, and Color Information Archiving. A more full description of capabilities and functionality can be found on the ICC web site, http://www.color.org/iccmax.xalter.

Note: The code in DemoIccMAX was initially based on the SampleICC and IccXML open source projects, and therefore concepts, files and data structures within DemoIccMAX may have similarities (as well as various differences) to those in the SampleICC and IccXML projects.

Overview

Within the DemoIccMAX project are several libraries and tools as follows:

  • Libraries that allow applications to interact with iccMAX profiles

    • IccProfLib - The DemoIccMAX IccProfLib project represents an open source & cross platform reference implementation of a C++ library for reading, writing, applying, manipulating iccMAX color profiles defined by the iccMAX profile specification. Class and object interaction documentation for IccProfLib can be found at ().

      • There are no intentional discrepancies between the DemoIccMAX implementation and the iccMAX specification. If any should occur then this should be brought to the attention of and resolved by the DemoIccMAX project team within the Architecture Working Group of the ICC organization.

        Though SampleICC provides a sample implementation, it does NOT represent a reference implementation of ICC.1 color management.

    • IccLibXML - The DemoIccMAX IccLibXML project contains a parallel C++ extension library (IccLibXML) which provides the ability to interact with the objects defined by IccProfLib using an XML representation thus allowing iccMAX profiles to be expressed as or created from text based XML files. The IccLibXML project has a dependencies on the libxml project (which also has a dependency on iconv which must be separately installed on windows platforms).

  • Tools based upon these libraries

    For command line arguments running the application without any arguments will display help information about command line options.

    • IccToXML is a cross platform command line tool that allows both legacy ICC and iccMAX profiles to be expressed using an XML representation. This allows for profiles to be converted to a textual representation that can be directly edited using a text editor and then converted back to ICC/iccMAX profile formats using IccFromXML.

      • This tool is dependent upon the IccLibXML project (above) as well as libXML and iconv.
    • IccFromXML is a cross platform command line tool that allows both legacy ICC and iccMAX profiles to be created from the same XML representation provided by IccToXML. A schema for iccXML files is forthcoming but can be determined using the FromXML() and ToXML() member functions defined in IccLibXML. The IccFromXML tool provides a simple direct method to create and manipulate iccMAX based profiles.

      • This tool is dependent upon the IccLibXML project (above) as well as libXML2 and iconv.
    • IccApplyNamedCmm is a cross platform command line tool that allows a sequence of legacy ICC and/or iccMAX profiles to be applied to colors defined in a text based input profile outputting the results to the console, and can be redirected to a output text file. Example source text files can be found in Testing/ApplyDataFiles. The IccApplyNamedCmm application provides a basis for testing various features of iccMAX.

    • IccApplyProfiles is a cross platform command line tool that allows a sequence of legacy and/or iccMAX profiles to a source TIFF image resulting in a destination TIFF image. The final destination profile can optionally be embedded in the resulting TIFF image.

      • This tool has a dependency on the LibTIFF project.
    • IccDumpProfile is a cross platform command line tool that allows information from a legacy ICC and or iccMAX profile to be output to the console. Data with non-printable values are replaced with '?'. Output from this tool is not guaranteed to be ASCII or UTF-8, but line-endings are consistent for a given platform.

      Detailed validation messages start with either "Warning!", "Error!" or "NonCompliant!". The overall status of validation is reported 2 lines below the line starting "Validation Report" and can be located using the following simple grep:

      grep --text -A 3 "^Validation Report" out.txt
    • IccRoundTrip is a cross platform command line tool that allows round trip colorimetric processing characteristics of rendering intent of a profile to be evaluated. (Evaluation goes from device values to PCS to establish initial PCS values. These are then converted to device values and then PCS values for the first round trip. Second round trip comparison then converts the second PCS values to device values to PCS values for comparison to the second PCS values.

    • IccSpecSepToTiff is a cross platform command line tool that combines separate individual TIFF images associated with different spectral wavelengths into a single multi-sample per pixel TIFF image. An iccMAX based profile can optionally be embedded in the resulting TIFF image.

      • This tool has a dependency on the LibTIFF project.
    • IccTiffDump is a cross platform command line tool that outputs header and embedded ICC profile information about a TIFF image to the console. This tool has a dependency on the LibTIFF project.

      • This tool has a dependency on the LibTIFF project.
    • RefIccLabsCMM provides a MacOS-X based Color Management Module that can be used within the ColorSync environment.

      • Many features of iccMAX based profiles are not accessible due to the limitation in support for only legacy ICC concepts within ColorSync.
    • wxProfileDump provides a wxWidgets GUI based iccMAX and legacy ICC profile inspector tool. The code for this tool is based on wxWidgets 2.x, and is therefore dependent on this version of wxWidgets. At present only Windows based testing has been performed on this (though wxWidgets is a cross-platform development environment).

      A development effort to port this tool to the cross-platform QT development environment is greatly needed.

Example iccMAX Profiles

XML files are provided that can be used to create example iccMAX profiles. The CreateAllProfiles.bat file uses the iccFromXML tool to create ICC profiles for each of these XML files. The XML files can be found in the following folders:

This folder contains profiles that demonstrate color modeling using the Calculator MultiProcessElement. The srgbCalcTest profile exercises all specified calculator operations.

This folder contains profiles that demonstrate spectral modeling of display profiles allowing for late binding of the observer using MultiProcessElements that are transformed at startup to colorimetry for the desired observer.

This folder contains 3 channel encoding class profiles. Both "name only" profiles as well as fully specified profiles are present.

This folder contains named color profiles showcasing features such as tints, spectral reflectance, and fluorescence (with and with out sparse notation).

This folder contains various profiles that can be used to define Profile Connection Conditions (PCC). All profiles are abstract profiles that perform no operation to PCS values. However, all profiles contain fully defined PCC tags that provide information that can be used to define rendering for various observers and illuminants. Profiles that utilize both absolute colorimetry as well as Material Adjusted colorimetry are present.

This folder contains various profiles that convert data to/from/between a spectral reflectance PCS. The argbRef (AdobeRGB) and srgbRef (sRGB) convert RGB values to/from spectral reflectance. RefDecC, RefDecH, and RefIncW are abstract spectral reflectance profiles that modify "chroma", "hue", and "lightness" of spectral reflectance values in a spectral reflectance PCS. The argbRef, srgbRef, RefDecC, RefDecH, RefIncW profiles all estimate and/or manipulate spectral reflectance using Wpt based spectral estimation (see chapter 7 of http://scholarworks.rit.edu/theses/8789/. Additionally, examples of 6 channel abridged spectral encoding is provided.

Project Build Considerations

Dependencies

Windows

The project solution files BuildAll.sln for various versions of the Microsoft Visual Studio development IDE can be found in the ./Build/MSVC folder. This references additional .vcproj files for the various libraries and applications provided by DemoIccMAX. Projects without any further dependencies should build and link correctly. Both 32 and 64 bit compile options are supported. Some of the projects have further dependencies on third party libraries requiring that the SDK libraries are installed, and some system environment variables need to be set to correctly reference the include files and libraries. (Note: Projects with additional dependencies may not correctly build if these libraries and environment variable are not set up before running Visual Studio).

The dependency on libxml2 and iconv by the IccLibXML library as well as the IccToXML and IccFromXML applications requires that these SDKs are accessible, and are referenced using the system environment variable VendorTreeDir with various sub-directories beneath. Macros for the location of each of these third party libraries is defined in [BuildDefs.props](Build/MSVC/BuildDefs.props). 64-bit versions of these SDKs can be found on the gnome website.

For example:

ICONV=C:\DevLibs\iconv\iconv-.9.2
LIBXML2=C:\DevLibs\libxml2\libxml2-2.7.8

The dependency on libtiff by the IccApplyProfiles, IccSpecSepToTiff, and IccTiffDump tools requires that the libtiff SDK is accessible, and is referenced using the system environment variables LIBTIFF_DLIB (debug library to use), LIBTIFF_INCLUDE, LIBTIFF_LIB (release library to use), and LIBTIFF_LIBDIR.

For example:

LIBTIFF_DLIB=libtiff.lib
LIBTIFF_INCLUDE=C:\DevLibs\libtiff\tiff-4.0.3\libtiff
LIBTIFF_LIB=libtiff.lib
LIBTIFF_LIBDIR=C:\DevLibs\libtiff\tiff-4.0.3\libtiff

The dependency on wxWidgets by the wxProfileDump tool requires that the wxWidgets SDK is accessible, and is reference using the system environment variables WXWIN and WXVER.

For example:

WXWIN=C:\DevLibs\WXWidgets\wxWidgets-2.8.11
WXVER=28

When the ICC_USE_EIGEN_SOLVER is defined in IccProfLibConf.h then the Calc element solv operator will be implemented using the Eigen math C++ template library, http://eigen.tuxfamily.org/index.php?title=Main_Page. It must be referenced using the system environment variable EIGEN.

For example:

EIGEN=C:\DevLibs\eigen\eigen-3.2.8

MacOS-X

XCODE projects can be found in each of the library and project folders that are presently supported for building on the MacOS-X platform. The file Build/XCode/BuildAll.sh contains a bash Terminal script that can be used to build all of the XCODE projects.

Header files and binaries for the libtiff and libxml libraries need to be manually installed before the BuildAll.sh script is executed. The libtiff header files need to be placed in the Build/XCode/libtiff folder (specified by the LibTifSetup.txt file in this folder). The libxml header files need to be placed in the Build/XCode/libxml folder (specified by the LibXmlSetup.txt file in this folder). (Note: Projects with additional dependencies may not correctly build if these folders not set up before running the BuildAll.sh script).

The BuildAll.sh script file will make a copy of the libIccProfLib.a and libIccXML.a library binaries into the Build/XCode/lib folder. The libraries in Build/XCode/lib are then referenced by the rest of the projects in DemoIccMAX. Executables for the various tools will be placed into the Testing folder after a successful run of BuildAll.sh.

CMake

Cmake builds should work cross platform. The source archive contains a CMake build configuration, which can be used to build on the command line with make or ninja, or generate a project for a KDevelop or Eclipse or for the platform specific XCode and VC++ IDEs.

Note: for historic reasons, the CMake system still uses the name "RefIccMAX"

Compilation

Typical create a out of source build directory and specify an install path:

mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=$HOME/.local ../Build/Cmake
make help
make
make install
Build Flags

Use -DCMAKE_BUILD_TYPE=Debug, -DCMAKE_BUILD_TYPE=Release or one of the other CMake build types.

Typical cmake flags like CMAKE_CXX_FLAGS can be used to tune compilation. For development ... -DCMAKE_CXX_FLAGS="-Wextra -Wimplicit-fallthrough=0 -g" is recommended, but this will not be warning free!.

Note: -Wimplicit-fallthrough=0 disables case fall-through warnings on switch statements as this is actively used (e.g. in IccConvertUTF.cpp). There will also be many -Wsign-compare warnings and a few -Wenum-compare and -Wdeprecated-copy warnings.

  • ENABLE_TESTS - default is ON
  • ENABLE_TOOLS - default is ON
  • ENABLE_SHARED_LIBS - default is ON
  • ENABLE_STATIC_LIBS - default is ON
  • ENABLE_INSTALL_RIM - install no files if build as subproject
  • USE_SYSTEM_LIBXML2 - default is OFF

Linux Packages

  • Pre Release Binaries - Open Build Service OBS

Linux Issues and Solutions

You may also need to set LD_LIBRARY_PATH to CMAKE_INSTALLPREFIX/lib so that libIccProfLib2.so and libIccXML.so shared libraries can be located at runtime.

export LD_LIBRARY_PATH=$HOME/.local/lib:$LD_LIBRARY_PATH

When running iccDumpProfileGui under X-Windows the following error messages may be seen on the console:

libGL error: No matching fbConfigs or visuals This can be fixed with:

export LIBGL_ALWAYS_INDIRECT=1

libGL error: failed to load driver: swrast This can be fixed with:

sudo apt-get install -y mesa-utils libgl1-mesa-glx
/usr/local/lib/libgnutls.so.30: version `GNUTLS_3_6_3' not found (required by /usr/lib/x86_64-linux-gnu/gio/modules/libgiognutls.so)
Failed to load module: /usr/lib/x86_64-linux-gnu/gio/modules/libgiognutls.so

The above error messages appear to be harmless, but running apt-cache policy libgnutls30 or gntls-cli -v will likely indicate a different (later) version of gnutls.

License

The ICC Software License

demoiccmax's People

Contributors

art1pirat avatar beku avatar darrenc-efi avatar digimatic avatar jamesvogh avatar jpap avatar majormurphy avatar maxderhak avatar naftaly avatar nicnilov avatar petervwyatt avatar ramzes2 avatar rogerhscottgt avatar xsscx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

demoiccmax's Issues

Excessive memory consumption and bad performance for Google SKIA profiles/fuzz/curv_size_overflow.icc

When running "iccDumpProfile" CLI utility on PC or Linux with the Google SKIA file "profiles/fuzz/curv_size_overflow.icc" and either or both -v or all options, RefIccMax consumes excessive memory (multiple GBs) and is exceptionally slow as a result. wxDumpProfile on PC is much faster and does not seem to suffer this (but I did not check the code). Without -v or all options "iccDumpProfile" runs very quickly like wxDumpProfile.

As the ICC profile filename suggests, the root cause is that the RGB TRC 'curv' have counts (n) of 2,147,484,348 which then attempts to allocate gigantic buffers * sizeof(float)! This is because the ICC file has been fuzzed and the corresponding bytes for count in the file are all 0xFF... (so, yes, it is malformed).

Problematic code is in IccProfLib/IccTagLut.cpp, function bool CIccTagCurve::SetSize(...) from line 442 (https://github.com/InternationalColorConsortium/RefIccMAX/blob/8da81e9151581161a582dbc4ca0ed8220aba02a9/IccProfLib/IccTagLut.cpp#L442). Would suggest that santity checks on the magnitude of count (n) prior to doing malloc/icRealloc are required. There may even be a maximum possible value for count given that the data for 'curv' are all uInt16Numbers according to ICC.1 v4.3.0 and the curves may have some precision requirements but all that color theory is beyond me...

Also suggest checking that all other malloc/icRealloc calls in the codebase are also range-checked prior to calls.

To get the Google SKIA ICC corpus and skcms/profiles/fuzz/curv_size_overflow.icc:

git clone https://skia.googlesource.com/skcms    ## quite small repo (~180MB), with corpus in 'profiles' folder and below
cd skcms/profiles/fuzz

Color management result by CMM may be "-nan(ind)"

I noticed that when I apply the profile below to CMM, "-nan(ind)" may be returned.

InputProfile : ICCProfile_sRGB_v5.xml.icc
OutputProfile : ICCProfile_AdobeRGB_v5.xml.icc

For example, if you input a RGB device value = ( 0, 0, 64) (normalized RGB value = ( 0, 0, 0.2510),
the output will be a normalized RGB value = ( -nan(ind), -nan(ind), 0.2462).

This is because x is slightly negative in the calculation of pow (float x, float y) in the following part, probably because of a calculation error, and it is out of the definition range.

default:
return (icFloatNumber)(pow(m_params[1] * v + m_params[2], m_params[0]) + m_params[3]);

Before calculating the pow, I think it might be a good idea to include a process such as rounding the range of x to 0-1.
Alternatively, improvements may be needed elsewhere.

I attached the sample code and profiles.
TestSample.zip

Thank you for your contribution.

Markup issues in some Testing examples

In RefIccMax-2.0.16:
A couple of minor issues with the mark-up in the xml examples in the Testing folder:
In several 'camera' examples including CameraModel.xml:
... is closed with instead of
is closed with

When these are corrected, there is a stack underflow at line 72: [mul] 33

Minor alignment issue for B Curve parsing in CIccTagLutAtoB::Read

Though I doubt this comes up in actual ICC profiles, I noticed that when parsing the B curves for the AtoB / BtoA LUT types, the offset realignment is wrong - it realigns based on the offset for the matrix instead of the B curve offset. You can see that the M & A curves are both correct and align to their respective offsets, so it's just the B curve that has this wrong. It's a minor thing that tripped me up when I was checking how the parsing code handles curve alignment.

See the diff below for the proposed fix. It feels a bit silly to do a pull request for a literal one-character change, but I can do that if it would be helpful.

diff --git a/IccProfLib/IccTagLut.cpp b/IccProfLib/IccTagLut.cpp                     
index 28bb070..3289370 100644                                                        
--- a/IccProfLib/IccTagLut.cpp                                                       
+++ b/IccProfLib/IccTagLut.cpp                                                       
@@ -3846,7 +3846,7 @@ bool CIccTagLutAtoB::Read(icUInt32Number size, CIccIO *pIO)    
       if (!pCurves[i]->Read(nEnd - pIO->Tell(), pIO))                               
         return false;                                                               
                                                                                     
-      if (!pIO->Sync32(Offset[1]))                                                  
+      if (!pIO->Sync32(Offset[0]))                                                  
         return false;                                                               
     }                                                                               
   }                                                                                 

Custom Names Color Space or Profile

Hi, I am trying to figure out how to programatically create a "Spot Color" for use when generating a PDF programatically. I am hoping someone here may have some knowledge on whether it is possible to do that by creating a custom color space.

Unfortunately I know very little about creating a custom color space.

The application is developed in Swift on macOS and generates print ready PDF files. Some printing required the use of SPOT colors - so solid colors that cannot be printed using normal CMYK printing.

The printers need the PDF to have these elements printed using a custom named color space so their print systems will automatically pick up the components to be printed with the spot color.

I am hoping that perhaps I can use the DemoIccMAX libraries to create a custom profile of some sort that can be installed on macOS and subsequently used programatically.

So the related questions I have are:

  1. Is it possible to define a custom profile with a single color in XML and then use the DemoIccMAX libraries to generate a icc profile that can be installed on macOS. This single color can be green - the print shop doesn't use the actual color, they just use the specific name to identify the objects to be printed. They have a separate process to load the actual ink color. Typically this is required when printing white on black substrate - they need to use a solid white ink since you can't do white in CMYK.

  2. Is it possible to use these libraries to generate such a profile on the fly such that it can be used programatically by the macOS APIs such as

CGColorSpace.init(iccData:)
Creates an ICC-based color space using the ICC profile contained in the specified data.

Any assistance will be much appreciated.

Does it possible to create CMYK output icc profile using this SDK?

I'm a newbie with color technology and I'm interested in IccMax SDK.
I want to create a CMYK icc profile from some patches like IT8/7.4 CGATS.

These days I study Icc Profiles specifications V2, V4, Color Management(Wiley) and try to create an icc profile.
wow, it is a complex topic which involves a wide range of disciplines including computer science, numerical analysis, and colour science.

but I encountered some problems.
1)I don't know what data(format, values...) for APIs when I try to use these functions.
2)No any API document that I don't know how to start.
3)I can't find any examples for CMYK output icc profiling.

Q1)Do you have any plan to design CxF3 SDK for reading and writing?
Q2)Could you give me advice about creating CMYK output icc profile?

Thanks

IccProfLib public header list

Here comes a list of potential headers to be installed into a system location for API users. Comments are appreciated on what to exclude or what is missed.
SET( HEADERS_PUBLIC
${SRC_PATH}/IccProfLib/IccApplyBPC.h
${SRC_PATH}/IccProfLib/IccArrayBasic.h
${SRC_PATH}/IccProfLib/IccArrayFactory.h
${SRC_PATH}/IccProfLib/IccCAM.h
${SRC_PATH}/IccProfLib/IccCmm.h
${SRC_PATH}/IccProfLib/IccConvertUTF.h
${SRC_PATH}/IccProfLib/IccDefs.h
${SRC_PATH}/IccProfLib/IccEncoding.h
${SRC_PATH}/IccProfLib/IccEnvVar.h
${SRC_PATH}/IccProfLib/IccEval.h
${SRC_PATH}/IccProfLib/IccIO.h
${SRC_PATH}/IccProfLib/IccMatrixMath.h
${SRC_PATH}/IccProfLib/IccMpeACS.h
${SRC_PATH}/IccProfLib/IccMpeBasic.h
${SRC_PATH}/IccProfLib/IccMpeCalc.h
${SRC_PATH}/IccProfLib/IccMpeFactory.h
${SRC_PATH}/IccProfLib/IccMpeSpectral.h
${SRC_PATH}/IccProfLib/IccPcc.h
${SRC_PATH}/IccProfLib/IccPrmg.h
${SRC_PATH}/IccProfLib/IccProfile.h
${SRC_PATH}/IccProfLib/IccProfLibConf.h
${SRC_PATH}/IccProfLib/IccProfLibVer.h
${SRC_PATH}/IccProfLib/IccSolve.h
${SRC_PATH}/IccProfLib/IccSparseMatrix.h
${SRC_PATH}/IccProfLib/IccStructBasic.h
${SRC_PATH}/IccProfLib/IccStructFactory.h
${SRC_PATH}/IccProfLib/IccTagBasic.h
${SRC_PATH}/IccProfLib/IccTagComposite.h
${SRC_PATH}/IccProfLib/IccTagDict.h
${SRC_PATH}/IccProfLib/IccTagFactory.h
${SRC_PATH}/IccProfLib/IccTag.h
${SRC_PATH}/IccProfLib/IccTagLut.h
${SRC_PATH}/IccProfLib/IccTagMPE.h
${SRC_PATH}/IccProfLib/IccTagProfSeqId.h
${SRC_PATH}/IccProfLib/IccUtil.h
${SRC_PATH}/IccProfLib/IccWrapper.h
${SRC_PATH}/IccProfLib/IccXformFactory.h
${SRC_PATH}/IccProfLib/icProfileHeader.h
${SRC_PATH}/IccProfLib/MainPage.h
)

Doesn't build on macOS

iccProfLib uses C++11 features (e.g. {} syntax for object initialisation), but the projects use the Xcode default for C++ dialect, which is C++98.

iccProfLib also contains invalid code, that casts enums to integers and tries to use values outside their valid range (e.g. in GetMeasurementFlareName) which is undefined behaviour. Clang errors on this by default, which can technically be silenced with -Wno-enum-constexpr-conversion although that's not a real solution (Clang doesn't guarantee the runtime behaviour will be as the code expects) and a performance pessimisation.

Beyond that, the iccProfLib builds as x86-64 only but all the subprojects (e.g. IccApplyNamedCmm) use the default value for the target architectures (which is currently x86_64 and arm64). So they all fail to link due to the missing arm64 slice.

RefIccMAXCmm also fails to build because it's using ColorSync types (e.g. CMError) which seemingly don't exist anymore (they were deprecated more than a decade ago, so I assume they've finally be outright removed from the framework).

The macOS deployment target is also being set to (or defaulting to?) 10.11, but modern Xcode doesn't support earlier than 10.13. This nominally just results in a warning, although it's possible it's screwing other things up too (hard to tell with so many other errors occurring in parallel).

IccLibXML.xcodeproj is missing targets for the actual command line tools - IccToXML et al.

Bugs from Fuzzing

Bug 1 - Heap Buffer Overflow in CIccCLUT::Interp3d | CVE-2023-46866

Patch in PR #64

Severity: Reference Implementation | High

Description

A heap buffer overflow has been identified in the CIccCLUT::Interp3d method. This vulnerability can lead to potential crashes or undefined behavior when certain conditions are met.

Steps to Reproduce

Utilize the CIccCLUT::Interp3d method on a CIccCLUT object under conditions where m_nNumPoints * m_nOutput equals 0.
Attempt to access indices beyond the allocated size of the m_pData array.

Debug Session

(lldb) fr se 5
frame #5: 0x0000000100e8c982 libIccProfLib2.2.dylib`CIccCLUT::Interp3d(this=0x0000614000000440, destPixel=0x00007ff7bfefde80, srcPixel=0x00007ff7bfefde80) const at IccTagLut.cpp:2594:27
   2591	               return;
   2592	           }
   2593
-> 2594	           destPixel[i] = p[n000] * dF0 + p[n001] * dF1 + p[n010] * dF2 + p[n011] * dF3 +
   2595	                          p[n100] * dF4 + p[n101] * dF5 + p[n110] * dF6 + p[n111] * dF7;
   2596	       }
   2597	   }
(lldb) frame variable
(CIccCLUT *) this = 0x0000614000000440
(icFloatNumber *) destPixel = 0x00007ff7bfefde80
(const icFloatNumber *) srcPixel = 0x00007ff7bfefde80
(icUInt8Number) mx = '\xff'
(icUInt8Number) my = '\xff'
(icUInt8Number) mz = '\xff'
(icFloatNumber) x = 0
(icFloatNumber) y = 0
(icFloatNumber) z = 0
(icUInt32Number) ix = 0
(icUInt32Number) iy = 0
(icUInt32Number) iz = 0
(icFloatNumber) u = 0
(icFloatNumber) t = 0
(icFloatNumber) s = 0
(icFloatNumber) ns = 1
(icFloatNumber) nt = 1
(icFloatNumber) nu = 1
(icFloatNumber) dF0 = 1
(icFloatNumber) dF1 = 0
(icFloatNumber) dF2 = 0
(icFloatNumber) dF3 = 0
(icFloatNumber) dF4 = 0
(icFloatNumber) dF5 = 0
(icFloatNumber) dF6 = 0
(icFloatNumber) dF7 = 0
(icUInt32Number) maxIndex = 50331647
(icFloatNumber *) pStart = 0x00006020000002d0
(int) i = 0
(icFloatNumber *) p = 0x00006020000002d0
(lldb) dis -s $pc-32 -c 24
libIccProfLib2.2.dylib`CIccCLUT::Interp3d:
    0x100e8c962 <+2978>: loopne 0x100e8c961               ; <+2977> at IccTagLut.cpp

Symptoms

  • The program crashes with an AddressSanitizer report indicating a heap-buffer-overflow in CIccCLUT::Interp3d.
  • The value of m_nNumPoints * m_nOutput is 0, indicating that the m_pData array might not have been allocated or is of size 0.
  • Attempts are made to access indices as high as 3 and potentially up to 50331647 (as indicated by the maxIndex variable).

Potential Causes

  • Improper initialization or setup of the CIccCLUT object.
  • Possible errors in the copy constructor or assignment operator of CIccCLUT.
    -The m_pData array might be reallocated with a different size elsewhere in the code.
    -Invalid or corrupt input data affecting the CIccCLUT object's construction.

Bug 2 - Segmentation Fault in CIccXformMatrixTRC::GetCurve | CVE-2023-46867

Severity: Reference Implementation | High

Description

A segmentation fault (SEGV) has been identified in the CIccXformMatrixTRC::GetCurve method within the IccCmm.cpp file, specifically at line 5240. The crash appears to be due to a read memory access at the zero address, suggesting a potential null pointer dereference.

Steps to Reproduce

Invoke the CIccXformMatrixTRC::GetCurve method with specific input that triggers the SEGV.
The exact input causing this behavior needs further investigation.
Observe the crash due to a segmentation fault.

Crash Details

AddressSanitizer:DEADLYSIGNAL
=================================================================
==59095==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x000104511cd4 bp 0x7ff7bc556550 sp 0x7ff7bc556500 T0)
==59095==The signal is caused by a READ memory access.
==59095==Hint: address points to the zero page.
    #0 0x104511cd4 in CIccXformMatrixTRC::GetCurve(unsigned int) const IccCmm.cpp:5240
    #1 0x10451107a in CIccXformMatrixTRC::Begin() IccCmm.cpp:5100
    #2 0x1045394a8 in CIccCmm::Begin(bool, bool) IccCmm.cpp:8297
    #3 0x1045905a4 in CIccEvalCompare::EvaluateProfile(CIccProfile*, unsigned char, icRenderingIntent, icXformInterp, bool) IccEval.cpp:110
    #4 0x104591419 in CIccEvalCompare::EvaluateProfile(char const*, unsigned char, icRenderingIntent, icXformInterp, bool) IccEval.cpp:197
    #5 0x1039ae0d2 in main iccRoundTrip.cpp:168
    #6 0x7ff80dee53a5 in start+0x795 (dyld:x86_64+0xfffffffffff5c3a5)

==59095==Register values:
rax = 0x0000000000000000  rbx = 0x00007ff7bc556900  rcx = 0x0000100000000000  rdx = 0x0000000000000000
rdi = 0x00007ff7bc5562c0  rsi = 0x00007ff7bc556320  rbp = 0x00007ff7bc556550  rsp = 0x00007ff7bc556500
 r8 = 0x0000604000001610   r9 = 0xf3f3f300f1f1f100  r10 = 0x00007fffffffffff  r11 = 0xffffffffffffff20
r12 = 0x00007ff7bc557590  r13 = 0x0000000000000000  r14 = 0x00000001039addb0  r15 = 0x00007ff7bc557710
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV IccCmm.cpp:5240 in CIccXformMatrixTRC::GetCurve(unsigned int) const

Symptoms

The program crashes with an AddressSanitizer report indicating a SEGV in CIccXformMatrixTRC::GetCurve.
The memory access causing the SEGV is a read operation from address 0x000000000000, which points to the zero page.
The crash occurs specifically at line IccCmm.cpp:5240.

Potential Causes

Dereferencing a null pointer or uninitialized pointer in the CIccXformMatrixTRC::GetCurve method.
An invalid curve index or parameter passed to the method, leading to out-of-bounds memory access.
Memory corruption elsewhere in the application affecting the behavior of the CIccXformMatrixTRC::GetCurve method.

Bugs 3 - 6

Bug Report: Undefined Behavior in IccTagLut.cpp and IccProfileXml.cpp

Severity: Reference Implementation | High

The UndefinedBehaviorSanitizer tool has identified multiple instances of undefined behavior within the IccTagLut.cpp and IccProfileXml.cpp files.

Bug 3 Description

File: IccTagLut.cpp
Line: 1798
Issue: Index -1 is being used to access an array of type icUInt32Number[16], which results in out-of-bounds access.

Bug 4 Description

File: IccTagLut.cpp
Line: 1799
Issue: Index -1 is being used to access an array of type icUInt8Number[16], which results in out-of-bounds access.

Bug 5 Description

File: IccProfileXml.cpp
Line: 128
Issue: Loading a value 2543294359 which is not a valid value for the type icPlatformSignature.

Bug 6 Description

File: IccProfileXml.cpp
Line: 129
Issue: Loading a value 2543294359 which is not a valid value for the type icPlatformSignature.

Bug 7 - Heap Buffer Overflow in CIccXmlArrayType::ParseText | CVE-2023-47249

Severity: Reference Implementation | High

Description

A heap buffer overflow has been identified in the function CIccXmlArrayType::ParseText at IccUtilXml.cpp:1003:10. This function is designed to parse text into an array, with a specific instantiation for unsigned short. The buffer overflow occurs during the parsing process, specifically in a loop condition where a buffer bound check fails, leading to an out-of-bounds read.

Variables at Crash Time:
pBuf: A pointer to the buffer where parsed data is stored.
nSize: The size of the buffer (4096).
szText: A pointer to the text being parsed.
n: Counter variable, which is also 4096 at the time of the crash.
Crash Location in Code:

The crash occurs in the loop: while (*szText && n<nSize) {.
The error indicates that when n equals nSize, the loop still attempts to read *szText, which is beyond the allocated buffer.

Steps to Reproduce

PoC

Testing % ./iccFromXML mcs/17ChanWithSpots-MVIS.xml mcs/17ChanWithSpots-MVIS.icc

Crash Details

mcs % ../iccFromXML 17ChanWithSpots-MVIS.xml 17ChanWithSpots-MVIS.icc
...
SUMMARY: AddressSanitizer: heap-buffer-overflow IccUtilXml.cpp:1003 in CIccXmlArrayType<unsigned short, (icTagTypeSignature)1969828150>::ParseText(unsigned short*, unsigned int, char const*)

Bug 8 - Floating Point Error in iccSpecSepToTiff.cpp at line 120

Patch in PR #64

Reproduction

./iccSpecSepToTiff out.tif 0 0 Overprint/17ChanData.txt 1 2 ~/Documents/2225-original.icc

Description

Arithmetic Error:

The crashing line (-> 0x100006251 <+1585>: idivl 0x230(%rbx)) suggests a division operation.
The corresponding source code line (120 n = (end-start)/step + 1;) is performing a division operation. If step is zero, this operation will cause a division by zero error, leading to an FPE.

Bug 9 SUMMARY: AddressSanitizer: heap-buffer-overflow IccUtilXml.cpp:1062 in CIccXmlArrayType<float, (icTagTypeSignature)1717793824>::ParseText(float*, unsigned int, char const*)

mcs % lldb -- ../../Build/Tools/IccFromXml/iccFromXML 18ChanWithSpots-MVIS.xml 18ChanWithSpots-MVIS.icc
(lldb) target create "../../Build/Tools/IccFromXml/iccFromXML"
Current executable set to 'DemoIccMAX-master/Build/Tools/IccFromXml/iccFromXML' (x86_64).
(lldb) settings set -- target.run-args  "18ChanWithSpots-MVIS.xml" "18ChanWithSpots-MVIS.icc"
(lldb) r
Process 79070 launched: 'DemoIccMAX-master/Build/Tools/IccFromXml/iccFromXML' (x86_64)
=================================================================
==79070==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x00010040340c at pc 0x000100990dc5 bp 0x7ff7bfefac70 sp 0x7ff7bfefac68
READ of size 1 at 0x00010040340c thread T0
    #0 0x100990dc4 in CIccXmlArrayType<float, (icTagTypeSignature)1717793824>::ParseText(float*, unsigned int, char const*) IccUtilXml.cpp:1062
    #1 0x100992462 in CIccXmlArrayType<float, (icTagTypeSignature)1717793824>::ParseTextArrayNum(char const*, unsigned int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>&) IccUtilXml.cpp:818
    #2 0x10094e784 in icCLutFromXml(_xmlNode*, int, int, icConvertType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>&) IccTagXml.cpp:3544
    #3 0x1008b46ff in CIccMpeXmlExtCLUT::ParseXml(_xmlNode*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>&) IccMpeXml.cpp:1935
    #4 0x1008bf990 in CIccMpeXmlCalculator::ParseImport(_xmlNode*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>&) IccMpeXml.cpp:2577
    #5 0x1008d170f in CIccMpeXmlCalculator::ParseXml(_xmlNode*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>&) IccMpeXml.cpp:3094
    #6 0x10095561d in CIccTagXmlMultiProcessElement::ParseElement(_xmlNode*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>&) IccTagXml.cpp:4081
    #7 0x1009567b9 in CIccTagXmlMultiProcessElement::ParseXml(_xmlNode*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>&) IccTagXml.cpp:4141
    #8 0x10090b119 in CIccProfileXml::ParseTag(_xmlNode*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>&) IccProfileXml.cpp:711
    #9 0x10090c924 in CIccProfileXml::ParseXml(_xmlNode*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>&) IccProfileXml.cpp:820
    #10 0x10090cd5b in CIccProfileXml::LoadXml(char const*, char const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>*) IccProfileXml.cpp:877
    #11 0x10000406c in main IccFromXml.cpp:68
    #12 0x7ff816e9f365 in start+0x795 (dyld:x86_64+0xfffffffffff5c365)

0x00010040340c is located 0 bytes after 2259980-byte region [0x0001001db800,0x00010040340c)
allocated by thread T0 here:
    #0 0x101743a20 in wrap_malloc+0xa0 (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0xdca20)
    #1 0x10094d4f1 in icCLutFromXml(_xmlNode*, int, int, icConvertType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>&) IccTagXml.cpp:3439
    #2 0x1008b46ff in CIccMpeXmlExtCLUT::ParseXml(_xmlNode*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>&) IccMpeXml.cpp:1935
    #3 0x1008bf990 in CIccMpeXmlCalculator::ParseImport(_xmlNode*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>&) IccMpeXml.cpp:2577
    #4 0x1008d170f in CIccMpeXmlCalculator::ParseXml(_xmlNode*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>&) IccMpeXml.cpp:3094
    #5 0x10095561d in CIccTagXmlMultiProcessElement::ParseElement(_xmlNode*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>&) IccTagXml.cpp:4081
    #6 0x1009567b9 in CIccTagXmlMultiProcessElement::ParseXml(_xmlNode*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>&) IccTagXml.cpp:4141
    #7 0x10090b119 in CIccProfileXml::ParseTag(_xmlNode*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>&) IccProfileXml.cpp:711
    #8 0x10090c924 in CIccProfileXml::ParseXml(_xmlNode*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>&) IccProfileXml.cpp:820
    #9 0x10090cd5b in CIccProfileXml::LoadXml(char const*, char const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>*) IccProfileXml.cpp:877
    #10 0x10000406c in main IccFromXml.cpp:68
    #11 0x7ff816e9f365 in start+0x795 (dyld:x86_64+0xfffffffffff5c365)

SUMMARY: AddressSanitizer: heap-buffer-overflow IccUtilXml.cpp:1062 in CIccXmlArrayType<float, (icTagTypeSignature)1717793824>::ParseText(float*, unsigned int, char const*)
Shadow bytes around the buggy address:
  0x000100403180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x000100403200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x000100403280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x000100403300: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x000100403380: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x000100403400: 00[04]fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x000100403480: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x000100403500: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x000100403580: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x000100403600: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x000100403680: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==79070==ABORTING

Clang Static Analyzer Report

Logic error

Assigned value is garbage or undefined 2
Called C++ object pointer is null 3
Dereference of null pointer 13
Garbage return value 1
Result of operation is garbage or undefined 4
Uninitialized argument value 6
Unix API 4

Memory error

Bad deallocator 7
Double free 2
Memory leak 10
Use-after-free 8

Unix API

Allocator sizeof operand mismatch 1

Unused code

Dead assignment 28
Dead increment 3
Dead initialization 20
Dead nested assignment 1

Knowledgebase

https://bugs.chromium.org/p/project-zero/issues/detail?id=2225
https://bugs.chromium.org/p/project-zero/issues/detail?id=2226
https://srd.cx/cve-2022-26730/
https://srd.cx/cve-2023-32443/
Clang Static Analyzer Report https://xss.cx/2023/10/29/src/demomax-clang-static-analysis/
Pull Request #53
icFixXml function [CVE-2023-46602]
CIccPRMG::GetChroma function [CVE-2023-46603]

Debugging Aids

Build

cmake -DCMAKE_INSTALL_PREFIX=$HOME/.local \
      -DCMAKE_BUILD_TYPE=Debug \
      -DCMAKE_CXX_FLAGS="-g -fsanitize=address -fno-omit-frame-pointer -Wall -std=c++17 -fprofile-instr-generate -fcoverage-mapping" \
      ../Build/Cmake
make

Other Overflow Examples

DemoIccMAX-master/Build/Tools/IccFromXml/iccFromXml DemoIccMAX-master/Testing/CMYK-3DLUTs/CMYK-3DLUTs2.xml DemoIccMAX-master/Testing/CMYK-3DLUTs/CMYK-3DLUTs2.icc
DemoIccMAX-master/Build/Tools/IccFromXml/iccFromXml DemoIccMAX-master/Testing/ICS/Rec2100HlgFull-Part1.xml DemoIccMAX-master/Testing/ICS/Rec2100HlgFull-Part1.icc
DemoIccMAX-master/Build/Tools/IccFromXml/iccFromXml DemoIccMAX-master/Testing/ICS/Rec2100HlgFull-Part2.xml DemoIccMAX-master/Testing/ICS/Rec2100HlgFull-Part2.icc
DemoIccMAX-master/Build/Tools/IccFromXml/iccFromXml DemoIccMAX-master/Testing/Overprint/17ChanPart1.xml DemoIccMAX-master/Testing/Overprint/17ChanPart1.icc

IccEval.cpp at Line 139 - 172

    //  * Modified by @h02332 | David Hoyt
    // determine granularity
    if (!nGran) {
      CIccTag* tag = pProfile->FindTag(icSigAToB0Tag + (nIntent == icAbsoluteColorimetric ? icRelativeColorimetric : nIntent));

      if (!tag) {
          std::cerr << "Tag is nullptr!" << std::endl;
          return icCmmStatColorNotFound;
      }
      
      try {
          if (dynamic_cast<CIccTagLut16*>(tag) != nullptr) {
              std::cerr << "Unexpected object type detected!" << std::endl;
              // If there's a method to get more details about the tag, use it. If not, skip this line.
              // std::cerr << "Tag details: " << tag->GetDetails() << std::endl;
              std::cerr << "Actual object type: " << typeid(*tag).name() << std::endl;
          } else {
              std::cerr << "Tag is not of expected type!" << std::endl;
              std::cerr << "Actual object type: " << typeid(*tag).name() << std::endl;
          }
      } catch (const std::bad_typeid& e) {
          std::cerr << "Caught bad_typeid exception: " << e.what() << std::endl;
          return icCmmStatBadLutType;
      }

      CIccTagLutAtoB* pTag = dynamic_cast<CIccTagLutAtoB*>(tag);

      // Check if pTag is valid. If it's not, we set nGran to default value and skip further checks.
      if (!pTag || ndim == 3) {
          nGran = 33;
      } else {
          CIccCLUT* pClut = pTag->GetCLUT();
          nGran = pClut ? (pClut->GridPoints() + 2) : 33;
      }
    }

IccTagLut.cpp at Line 2523 - 2666

/**
 ******************************************************************************
 * Name: CIccCLUT::Interp3d
 * 
 * Purpose: Three dimensional interpolation function
 *
 * Args:
 *  Pixel = Pixel value to be found in the CLUT. Also used to store the result.
 * Modified by @h02332 | David Hoyt
 *******************************************************************************
 */
void CIccCLUT::Interp3d(icFloatNumber *destPixel, const icFloatNumber *srcPixel) const
{
    icUInt8Number mx = m_MaxGridPoint[0];
    icUInt8Number my = m_MaxGridPoint[1];
    icUInt8Number mz = m_MaxGridPoint[2];

    icFloatNumber x = UnitClip(srcPixel[0]) * mx;
    icFloatNumber y = UnitClip(srcPixel[1]) * my;
    icFloatNumber z = UnitClip(srcPixel[2]) * mz;

    icUInt32Number ix = (icUInt32Number)x;
    icUInt32Number iy = (icUInt32Number)y;
    icUInt32Number iz = (icUInt32Number)z;

    icFloatNumber u = x - ix;
    icFloatNumber t = y - iy;
    icFloatNumber s = z - iz;

    if (ix == mx) {
        ix--;
        u = 1.0;
    }
    if (iy == my) {
        iy--;
        t = 1.0;
    }
    if (iz == mz) {
        iz--;
        s = 1.0;
    }

    icFloatNumber ns = (icFloatNumber)(1.0 - s);
    icFloatNumber nt = (icFloatNumber)(1.0 - t);
    icFloatNumber nu = (icFloatNumber)(1.0 - u);

    icUInt32Number maxIndex = (mx + 1) * (my + 1) * (mz + 1) * m_nOutput - 1;

    icFloatNumber dF0 = ns * nt * nu;
    icFloatNumber dF1 = ns * nt * u;
    icFloatNumber dF2 = ns * t * nu;
    icFloatNumber dF3 = ns * t * u;
    icFloatNumber dF4 = s * nt * nu;
    icFloatNumber dF5 = s * nt * u;
    icFloatNumber dF6 = s * t * nu;
    icFloatNumber dF7 = s * t * u;

     icFloatNumber *pStart = &m_pData[ix * n001 + iy * n010 + iz * n100];

     for (int i = 0; i < m_nOutput; i++) {
         icFloatNumber *p = pStart + i;

         // Logging statements before the problematic line:
              std::cout << "Pointer p: " << p << std::endl;
              std::cout << "n000: " << n000 << ", Value: " << p[n000] << std::endl;
              std::cout << "n001: " << n001 << ", Value: " << p[n001] << std::endl;
              std::cout << "n010: " << n010 << ", Value: " << p[n010] << std::endl;
              std::cout << "n011: " << n011 << ", Value: " << p[n011] << std::endl;
              std::cout << "n100: " << n100 << ", Value: " << p[n100] << std::endl;
              std::cout << "n101: " << n101 << ", Value: " << p[n101] << std::endl;
              std::cout << "n110: " << n110 << ", Value: " << p[n110] << std::endl;
              std::cout << "n111: " << n111 << ", Value: " << p[n111] << std::endl;
         
          // ... Similarly for other indices ...
         
         // Log the maximum possible index and the current index
         std::cout << "Max Index: " << maxIndex << ", Current Index: " << (p + n111 - m_pData) << std::endl;

         if (p + n111 > m_pData + maxIndex) {
             std::cerr << "Potential overflow detected. Aborting." << std::endl;
             return;
         }

         // Try to safely access the value at p[n000]
         if (p + n000 > m_pData + maxIndex) {
             std::cerr << "Potential overflow detected. Aborting." << std::endl;
             return;
         } else {
             std::cout << "Value at (p + n000): " << p[n000] << std::endl;
         }

         if ((p + n001) >= (m_pData + maxIndex)) {
             std::cerr << "Out-of-bounds access detected for n001." << std::endl;
         }

         if ((p + n010) >= (m_pData + maxIndex)) {
             std::cerr << "Out-of-bounds access detected for n010." << std::endl;
         }

         if ((p + n011) >= (m_pData + maxIndex)) {
             std::cerr << "Out-of-bounds access detected for n011." << std::endl;
         }
         
         if ((p + n100) >= (m_pData + maxIndex)) {
             std::cerr << "Out-of-bounds access detected for n100." << std::endl;
         }
        
         if ((p + n101) >= (m_pData + maxIndex)) {
             std::cerr << "Out-of-bounds access detected for n101." << std::endl;
         }
         
         if ((p + n110) >= (m_pData + maxIndex)) {
             std::cerr << "Out-of-bounds access detected for n110." << std::endl;
         }
         
         if ((p + n111) >= (m_pData + maxIndex)) {
             std::cerr << "Out-of-bounds access detected for n111." << std::endl;
         }
         // Add logging statements before the problematic line:
          std::cout << "n000: " << n000 << std::endl;
          std::cout << "n001: " << n001 << std::endl;
          std::cout << "n010: " << n010 << std::endl;
          std::cout << "n011: " << n011 << std::endl;
          std::cout << "n100: " << n100 << std::endl;
          std::cout << "n101: " << n101 << std::endl;
          std::cout << "n110: " << n110 << std::endl;
          std::cout << "n111: " << n111 << std::endl;
         std::cout << "ix: " << ix << std::endl;
             std::cout << "iy: " << iy << std::endl;
             std::cout << "iz: " << iz << std::endl;
             std::cout << "n001: " << n001 << std::endl;
             std::cout << "n010: " << n010 << std::endl;
             std::cout << "n100: " << n100 << std::endl;
             std::cout << "pStart address: " << pStart << std::endl;
         
         // Before the problematic line
         std::cout << "Pointer p: " << p << std::endl;
         std::cout << "n000: " << n000 << std::endl;
         std::cout << "Address (p + n000): " << p + n000 << std::endl;

         
         destPixel[i] = p[n000] * dF0 + p[n001] * dF1 + p[n010] * dF2 + p[n011] * dF3 +
                        p[n100] * dF4 + p[n101] * dF5 + p[n110] * dF6 + p[n111] * dF7;
     }
 }

IccUtilXml.cpp at Line 421 - 491

//  * Modified by @h02332 | David Hoyt
class CIccDumpXmlCLUT : public IIccCLUTExec
{
public:
  CIccDumpXmlCLUT(std::string *xml, icConvertType nType, std::string blanks, icUInt16Number nSamples, icUInt8Number nPixelsPerRow)
  {
    m_xml = xml;
    m_nType = nType;
    m_blanks = blanks;
    m_nSamples = nSamples;
    m_nPixelsPerRow = nPixelsPerRow;
    m_nCurPixel = 0;
  }

    virtual void PixelOp(icFloatNumber* pGridAdr, icFloatNumber* pData)
    {
        if (!pData) {
            std::cerr << "Error: pData is nullptr." << std::endl;
            return;  // Early return if pData is null
        }

        int i;
        char buf[128];

        if (!(m_nCurPixel % m_nPixelsPerRow))
            *m_xml += m_blanks;

        switch(m_nType) {
            case icConvert8Bit:
                for (i=0; i<m_nSamples; i++) {
                    if (&pData[i] == nullptr) {  // Check if accessing pData[i] is valid
                        std::cerr << "Error: pData[i] is out of bounds." << std::endl;
                        return;
                    }
                    sprintf(buf, " %3d", (icUInt8Number)(pData[i]*255.0 + 0.5));
                    *m_xml += buf;
                }
                break;
            case icConvert16Bit:
                for (i=0; i<m_nSamples; i++) {
                    sprintf(buf, " %5d", (icUInt16Number)(pData[i]*65535.0 + 0.5));
                    *m_xml += buf;
                }
                break;
            case icConvertFloat:
            default:
                for (i=0; i<m_nSamples; i++) {
                    sprintf(buf, " %13.8f", pData[i]);
                    *m_xml += buf;
                }
                break;
        }
        m_nCurPixel++;
        if (!(m_nCurPixel % m_nPixelsPerRow)) {
            *m_xml += "\n";
        }
    }

    void Finish()
    {
        if (m_nCurPixel % m_nPixelsPerRow) {
            *m_xml += "\n";
        }
    }

    std::string *m_xml;
    icConvertType m_nType;
    std::string m_blanks;
    icUInt16Number m_nSamples;
    icUInt8Number m_nPixelsPerRow;
    icUInt32Number m_nCurPixel;
};

DORKs for IccXmlLib or IccProfLib

intext:"libiccxml" OR intext:"iccproflib" "International Color Consortium" filetype:pdf OR filetype:txt OR filetype:md OR filetype:xml OR filetype:txt OR filetype:cpp
"Libiccxml" OR "iccproflib"
"iccxmllib" OR "iccproflib"

problem with compiling and linking using macOS

I can't get the CMake or XCode builds to work properly on MacOS and produce scripts that are portable to other Macs. Any advice on this would be much appreciated.

My system is:

  • MacOS Catalina (10.15.6)
  • XCode 12.2

CMake

The closest build command I've figured out is:

brew install libtiff
mkdir dist/ && cd dist/ && cmake -DENABLE_STATIC_LIBS=ON -DENABLE_SHARED_LIBS=OFF ../Build/Cmake && make && make install

This produces a valid build for my machine, but the scripts have a link to libtiff - as installed by homebrew, libtiff doesn't come installed on MacOS by default. So this script is does not work on other people's machines.

$ otool -L Tools/IccApplyProfiles/iccApplyProfiles
	/usr/local/opt/libtiff/lib/libtiff.5.dylib (compatibility version 11.0.0, current version 11.0.0)
	/System/Library/Frameworks/Carbon.framework/Versions/A/Carbon (compatibility version 2.0.0, current version 164.0.0)
	/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit (compatibility version 1.0.0, current version 275.0.0)
	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 904.4.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1292.0.0)

Is there a way to build iccApplyProfiles on MacOS so that it can be used on other Macs? I think this might be called "relocatable packages" and involve including libtiff within the builds somehow - but I'm not sure. I haven't been able to figure it out.

XCode

I also tried building using XCode, but it did not work.

after copying the required files, as per the README:

$ cd Build/XCode && ./BuildAll.sh   
Command line invocation:
    /Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -target IccProfLib-macOS -configuration Release

note: Using new build system
note: Planning build
note: Using build description from disk

** BUILD SUCCEEDED **

cp: Build/Release/usr is a directory (not copied).
Command line invocation:
    /Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -target IccLibXML-macOS -configuration Release

note: Using new build system
note: Planning build
note: Using build description from disk

** BUILD SUCCEEDED **

cp: build/Release/usr is a directory (not copied).
Command line invocation:
    /Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -target IccApplyNamedCMM -configuration Release

note: Using new build system
note: Planning build
note: Using build description from disk
error: The linked library 'libIccProfLib.a' is missing one or more architectures required by this target: arm64. (in target 'IccApplyNamedCMM' from project 'IccApplyNamedCMM')

** BUILD FAILED **

cp: build/Release/IccApplyNamedCmm: No such file or directory
...

Inconsistent validation results (missing validation checks)

Hi,
we included IccProfLib into one of our image validation tools. The tool calls CIccProfile::ReadValidate on embedded profiles.

We noticed that profiles validated with the IccDumpProfile CI Tool to be non-compliant, are still valid and compliant when tested with this IccProfLib call.
One real-world example we encountered: First tag data that is on an offset rather than immediately after tag table (as expected by the ICC standard).

It seems IccDumpProfile implements more non-compliant checks and warnings.
--> https://github.com/InternationalColorConsortium/DemoIccMAX/blob/master/Tools/CmdLine/IccDumpProfile/iccDumpProfile.cpp#L241-L304

Would it be possible to include those into IccProfLib as well to get consistent validation results and reports across all tools and libs in this project?

Library names

It might be worthwhile to consider related library names, as the two previous projects moved into a single on.

SampleICC (past): libSampleICC.a
IccXML (past): libIccXML.a
IccProfLib (now): libIccProfLib.a

proposed:
IccProfLib: libRefIccMaxProf.a
IccXML: libRefIccMaxXml.a

other ideas welcome

What kind of data that I need to prepare for creating an Icc Profile?

I'm a newcomer in Icc profile.

I saw a lot of examples in IccProfLib and RefIccMax, but I still no any ideas to create an Icc profile.
I have a big problem that what kind of data for creating an Icc Profile.
All examples are compiled success, but I don't know how to use it. because I don't known how to prepare data for input.
for example: create_CLUT_profile command tool

Could you give me some advice?
thanks

A/B input/output confusion.

While attempting to use iccToXml and iccFromXml to create a profile for "A CMYK (four channel)" to "B Lab (three channel)" the tool segfaulted. The issue is a confusion about properly keeping track of which of A and B are the input and the output. The "AtoB" and "BtoA" types do this fairly well, but the "Lut8" and "Lut16" types currently appear to always assume B is the input. This kinda works in a somewhat confusing way, but only when A and B have the same number of channels.

By creating a hack like bungeman@a963b3b (originally against sample-icc and iccxml-code because that's what I found first) I am able to create and round trip a simple CMYK profile like cmyk2x2.zip (zipped since I cannot attach a bare icc file here). Since this change isn't very clean at the moment I've decided to open this as an issue instead of as a pull request. Note that the messy part of this change is around informing the Lut classes of their direction, the changes to the classes to output correctly when they have the proper direction set seems to be correct.

problem with compiling

since two days I am trying to compile the project with no success unfortunately.
I have followed whatever instructions were mentioned on the home page of the project for Windows OS (e.g. setting up all the necessary system variables LIBXML2, LIBTIFF...etc.) and yet it doesn't work!

I needed however actually to include the libraries explicitly in all the projects in visual studio solution and still it doesn't work.

Clearer instructions would be appreciated on how to make it runs.

CMake option to exclude IccXML extension in build (and therefore libxml2 depdendency)

I am considering using IccProfLib to process some ICC profiles in a program. I do not need the (de)serialization of ICC profiles to(from) XML that the IccLibXML extension provides.

Unfortunately to build the project for IccProfLib without modification, we are forced to build IccXML, which means that we must have libxml2 installed as a dependency. This makes it more difficult to build IccProfLib using a cross compiler, because we must first cross-compile libxml2.

It would be nice to have a CMake var, for example, ENABLE_ICCXML that we can set to OFF (default ON to preserve existing behavior).

Compile Errors in PR 69 | CIccXformNDLut | CIccApplyNDLutXform | IccProfLib/IccCmm.h | IccProfLib/IccCmm.cpp

Compile Errors from PR #69
Commit b90ac3933da99179df26351c39d8d9d706ac1cc6

Passing Compile in PR #66
Commit f891074a0f1c9d61a3dfa53749265f8c14ed4ee6

PR 66 Reproduction

cd /tmp
wget https://github.com/InternationalColorConsortium/DemoIccMAX/archive/f891074a0f1c9d61a3dfa53749265f8c14ed4ee6.zip
unzip f891074a0f1c9d61a3dfa53749265f8c14ed4ee6.zip
cd DemoIccMAX-f891074a0f1c9d61a3dfa53749265f8c14ed4ee6/Build
cmake -DCMAKE_INSTALL_PREFIX=$HOME/.local -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-g -fsanitize=address,undefined -fno-omit-frame-pointer -Wall" -Wno-dev  Cmake
make -j$(nproc) 2>&1 | grep 'error:'

Result: Passing

PR 69 Reproduction

cd /tmp
wget https://github.com/InternationalColorConsortium/DemoIccMAX/archive/b90ac3933da99179df26351c39d8d9d706ac1cc6.zip
unzip b90ac3933da99179df26351c39d8d9d706ac1cc6.zip
cd DemoIccMAX-b90ac3933da99179df26351c39d8d9d706ac1cc6/Build
cmake -DCMAKE_INSTALL_PREFIX=$HOME/.local -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-g -fsanitize=address,undefined -fno-omit-frame-pointer -Wall" -Wno-dev  Cmake
make -j$(nproc) 2>&1 | grep 'error:'
...
DemoIccMAX-b90ac3933da99179df26351c39d8d9d706ac1cc6/Build/Cmake/../../IccProfLib/IccCmm.h:1246:23: error: unknown type name 'CIccXformNDLut'
DemoIccMAX-b90ac3933da99179df26351c39d8d9d706ac1cc6/Build/Cmake/../../IccProfLib/IccCmm.h:1246:23: error: unknown type name 'CIccXformNDLut'
DemoIccMAX-b90ac3933da99179df26351c39d8d9d706ac1cc6/Build/Cmake/../../IccProfLib/IccCmm.h:1246:23: error: unknown type name 'CIccXformNDLut'
DemoIccMAX-b90ac3933da99179df26351c39d8d9d706ac1cc6/Build/Cmake/../../IccProfLib/IccCmm.h:1246:23: error: unknown type name 'CIccXformNDLut'
DemoIccMAX-b90ac3933da99179df26351c39d8d9d706ac1cc6/IccProfLib/IccCmm.cpp:1923:22: error: out-of-line definition of 'CIccApplyNDLutXform' does not match any declaration in 'CIccApplyNDLutXform'
DemoIccMAX-b90ac3933da99179df26351c39d8d9d706ac1cc6/IccProfLib/IccCmm.cpp:1923:22: error: out-of-line definition of 'CIccApplyNDLutXform' does not match any declaration in 'CIccApplyNDLutXform'
DemoIccMAX-b90ac3933da99179df26351c39d8d9d706ac1cc6/IccProfLib/IccCmm.cpp:6306:33: error: no matching constructor for initialization of 'CIccApplyNDLutXform'
DemoIccMAX-b90ac3933da99179df26351c39d8d9d706ac1cc6/IccProfLib/IccCmm.cpp:6306:33: error: no matching constructor for initialization of 'CIccApplyNDLutXform'
DemoIccMAX-b90ac3933da99179df26351c39d8d9d706ac1cc6/Build/Cmake/../../IccProfLib/IccCmm.h:1246:23: error: unknown type name 'CIccXformNDLut'

Result: Not Passing

XCode project contains fixed paths

Running BuildAll.sh on OS X fails because project contains fixed paths

ex.
clang: error: no such file or directory: '/Development/ICC/ICCMax/RefIccMAX-2.0.17/IccXML/IccLibXML/IccMpeXml.cpp'

gamutBoundaryDescType encoding in IccFromXml

When a gamutBoundaryDescType tag is created in XML, only values from the first two vertices seem to be encoded in the profile by IccFromXml. After the first device value for the second vertex, the remainder of the data are encoded as zeros.

Lut16 / Lut8 Handling of PCSXYZ Color Space doesn't set up curves/matrix

The Lut16 & Lut8 types are supposed to have special handling when the input color space is PCSXYZ, which is the only time the matrix coefficients get used. From what I can tell, this special handling exists but never actually loads the matrix coefficients in or loads new curves into the B curves section. Is this correct, in that "in-the-wild" ICC profiles don't ever actually use the matrix coefficients correctly and they should thus be ignored, or should they be loaded in? If they should be ignored, perhaps the code that generates a new matrix and curves can be removed?

I took the Lut8 section of code I'm talking about and annotated it below:

void CIccTagLut8::SetColorSpaces(icColorSpaceSignature csInput, icColorSpaceSignature csOutput)
{
  if (csInput==icSigXYZData) {
    int i;

    if (!m_CurvesM && IsInputMatrix()) { //Transfer ownership of curves
      m_CurvesM = m_CurvesB;
      m_CurvesB = NULL;

      // ๐Ÿ‘‡ Why does this code allocate a new set of curves and do nothing with it?
      LPIccCurve *pCurves = NewCurvesB();
      CIccTagCurve *pCurve; 
      for (i=0; i<m_nInput; i++) {
        pCurves[i] = pCurve = (CIccTagCurve*)CIccTag::Create(icSigCurveType);
        pCurve->SetSize(0); 
      } 

      m_bUseMCurvesAsBCurves = true;
    } 

    if (!m_Matrix) {
      // ๐Ÿ‘‡ Why does this code allocate a new matrix and do nothing with it?
      CIccMatrix *pMatrix = NewMatrix();
      for (i=0; i<9; i++) {
        pMatrix->m_e[i] = icFtoD(m_XYZMatrix[i]);
      }

      pMatrix->m_bUseConstants=false;
    } 
  } 
  else {
    m_XYZMatrix[0] = m_XYZMatrix[4] = m_XYZMatrix[8] = icDtoF(1.0);
    m_XYZMatrix[1] = m_XYZMatrix[2] = m_XYZMatrix[3] = 
    m_XYZMatrix[5] = m_XYZMatrix[6] = m_XYZMatrix[7] = 0;
  } 

  CIccMBB::SetColorSpaces(csInput, csOutput);
}

export path libIccXML2.so.2

for me the correct export path was export LD_LIBRARY_PATH=$HOME/.local/lib64:$LD_LIBRARY_PATH
this is for the debug build flag in the instructions example

AddressSanitizer: heap-buffer-overflow on IccTagXml

Tested on OS - Ubuntu 22.04 LTS 5.15.0-72-generic #79-Ubuntu SMP x86_64 x86_64 x86_64 GNU/Linux

A heap based buffer overflow was identified on IccToXml while fuzzing the vulnerability is triggered with a crafted .icc profile file. Attaching the same for reference.

GDB:

(gdb) r sample.icc /dev/null 
Starting program: /DemoIccMAX/Build/Cmake/Tools/IccToXml/iccToXml sample.icc /dev/null
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7f6bc9c in icCurvesToXml (xml="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<IccProfile>\n  <Header>\n    <PreferredCMMType>ADBE</PreferredCMMType>\n    <ProfileVersion>4.20</ProfileVersion>\n    <ProfileDeviceClass>scnr</ProfileDeviceClass>"..., szName=0x7ffff7f99874 "MCurves", pCurves=pCurves@entry=0x61f7a0, numCurve=<optimized out>, numCurve@entry=3, nType=nType@entry=icConvertVariable, blanks=...) at /DemoIccMAX/IccXML/IccLibXML/IccTagXml.cpp:2991
2991	      IIccExtensionTag *pTag = pCurves[i]->GetExtension();
(gdb) 
(gdb) bt
#0  0x00007ffff7f6bc9c in icCurvesToXml (
    xml="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<IccProfile>\n  <Header>\n    <PreferredCMMType>ADBE</PreferredCMMType>\n    <ProfileVersion>4.20</ProfileVersion>\n    <ProfileDeviceClass>scnr</ProfileDeviceClass>"..., szName=0x7ffff7f99874 "MCurves", pCurves=pCurves@entry=0x61f7a0, numCurve=<optimized out>, numCurve@entry=3, 
    nType=nType@entry=icConvertVariable, blanks=...) at /DemoIccMAX/IccXML/IccLibXML/IccTagXml.cpp:2991
#1  0x00007ffff7f6cfc7 in icMBBToXml (
    xml="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<IccProfile>\n  <Header>\n    <PreferredCMMType>ADBE</PreferredCMMType>\n    <ProfileVersion>4.20</ProfileVersion>\n    <ProfileDeviceClass>scnr</ProfileDeviceClass>"..., pMBB=pMBB@entry=0x61f4b0, nType=nType@entry=icConvertVariable, blanks=..., bSaveGridPoints=true)
    at /DemoIccMAX/IccXML/IccLibXML/IccTagXml.cpp:3151
#2  0x00007ffff7f6f86c in CIccTagXmlLutAtoB::ToXml (this=0x61f4b0, 
    xml="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<IccProfile>\n  <Header>\n    <PreferredCMMType>ADBE</PreferredCMMType>\n    <ProfileVersion>4.20</ProfileVersion>\n    <ProfileDeviceClass>scnr</ProfileDeviceClass>"..., blanks=...) at /DemoIccMAX/IccXML/IccLibXML/IccTagXml.cpp:3798
#3  0x00007ffff7f58331 in CIccProfileXml::ToXmlWithBlanks (this=<optimized out>, this@entry=0x7fffffffe1e8, xml=..., blanks=...)
    at /DemoIccMAX/IccXML/IccLibXML/IccProfileXml.cpp:264
#4  0x00007ffff7f557ec in CIccProfileXml::ToXml (this=0x7fffffffe1e8, 
    xml="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<IccProfile>\n  <Header>\n    <PreferredCMMType>ADBE</PreferredCMMType>\n    <ProfileVersion>4.20</ProfileVersion>\n    <ProfileDeviceClass>scnr</ProfileDeviceClass>"...) at /DemoIccMAX/IccXML/IccLibXML/IccProfileXml.cpp:79
#5  0x0000000000403696 in main (argc=<optimized out>, argv=0x7fffffffe3b8) at /DemoIccMAX/IccXML/CmdLine/IccToXml/IccToXml.cpp:38
(gdb) i r
rax            0x61f7a0            6420384
rbx            0x1                 1
rcx            0x1                 1
rdx            0x624               1572
rsi            0x60c010            6340624
rdi            0x0                 0
rbp            0x1                 0x1
rsp            0x7fffffffd3f0      0x7fffffffd3f0
r8             0x624580            6440320
r9             0x0                 0
r10            0x7fffffffc9b0      140737488341424
r11            0xb6ff62935fcf2779  -5260377454638323847
r12            0x7fffffffd488      140737488344200
r13            0x61f7e0            6420448
r14            0x6                 6
r15            0x7fffffffd478      140737488344184
rip            0x7ffff7f6bc9c      0x7ffff7f6bc9c <icCurvesToXml(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, char const*, CIccCurve**, int, icConvertType, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)+588>
eflags         0x10202             [ IF RF ]
cs             0x33                51
ss             0x2b                43
ds             0x0                 0
es             0x0                 0
fs             0x0                 0
gs             0x0                 0
(gdb) 
rax            0x61f7a0            6420384
rbx            0x1                 1
rcx            0x1                 1
rdx            0x624               1572
rsi            0x60c010            6340624
rdi            0x0                 0
rbp            0x1                 0x1
rsp            0x7fffffffd3f0      0x7fffffffd3f0
r8             0x624580            6440320
r9             0x0                 0
r10            0x7fffffffc9b0      140737488341424
r11            0xb6ff62935fcf2779  -5260377454638323847
r12            0x7fffffffd488      140737488344200
r13            0x61f7e0            6420448
r14            0x6                 6
r15            0x7fffffffd478      140737488344184
rip            0x7ffff7f6bc9c      0x7ffff7f6bc9c <icCurvesToXml(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, char const*, CIccCurve**, int, icConvertType, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)+588>
eflags         0x10202             [ IF RF ]
cs             0x33                51
ss             0x2b                43
ds             0x0                 0
es             0x0                 0
fs             0x0                 0
gs             0x0                 0
(gdb)

ASAN:

==115400==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000118 at pc 0x7ffff7f03d71 bp 0x7fffffffb7d0 sp 0x7fffffffb7c8
READ of size 8 at 0x602000000118 thread T0
    #0 0x7ffff7f03d70 in icCurvesToXml(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, char const*, CIccCurve**, int, icConvertType, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) DemoIccMAX/IccXML/IccLibXML/IccTagXml.cpp:2991:32
    #1 0x7ffff7f07440 in icMBBToXml(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, CIccMBB*, icConvertType, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool) DemoIccMAX/IccXML/IccLibXML/IccTagXml.cpp:3151:12
    #2 0x7ffff7f10e17 in CIccTagXmlLutAtoB::ToXml(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) DemoIccMAX/IccXML/IccLibXML/IccTagXml.cpp:3798:13
    #3 0x7ffff7ebff07 in CIccProfileXml::ToXmlWithBlanks(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) DemoIccMAX/IccXML/IccLibXML/IccProfileXml.cpp:264:27
    #4 0x7ffff7eb930e in CIccProfileXml::ToXml(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&) DemoIccMAX/IccXML/IccLibXML/IccProfileXml.cpp:79:10
    #5 0x4d3da5 in main DemoIccMAX/IccXML/CmdLine/IccToXml/IccToXml.cpp:38:16
    #6 0x7ffff7319d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #7 0x7ffff7319e3f in __libc_start_main csu/../csu/libc-start.c:392:3
    #8 0x4224d4 in _start (DemoIccMAX/Build/Cmake/Tools/IccToXml/iccToXml+0x4224d4)

0x602000000118 is located 0 bytes to the right of 8-byte region [0x602000000110,0x602000000118)
allocated by thread T0 here:
    #0 0x4d128d in operator new[](unsigned long) (DemoIccMAX/Build/Cmake/Tools/IccToXml/iccToXml+0x4d128d)
    #1 0x7ffff7d260b8 in CIccMBB::NewCurvesM() DemoIccMAX/IccProfLib/IccTagLut.cpp:3595:15
    #2 0x7ffff7d260b8 in CIccTagLutAtoB::Read(unsigned int, CIccIO*) DemoIccMAX/IccProfLib/IccTagLut.cpp:3877:27
    #3 0x7ffff7c240e3 in CIccProfile::LoadTag(IccTagEntry*, CIccIO*, bool) DemoIccMAX/IccProfLib/IccProfile.cpp:1188:14
    #4 0x7ffff7c275d0 in CIccProfile::Read(CIccIO*, bool) DemoIccMAX/IccProfLib/IccProfile.cpp:748:10

SUMMARY: AddressSanitizer: heap-buffer-overflow DemoIccMAX/IccXML/IccLibXML/IccTagXml.cpp:2991:32 in icCurvesToXml(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, char const*, CIccCurve**, int, icConvertType, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)
Shadow bytes around the buggy address:
  0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff8000: fa fa 00 fa fa fa 00 fa fa fa 00 fa fa fa 00 fa
  0x0c047fff8010: fa fa fd fa fa fa fd fa fa fa 00 04 fa fa 00 fa
=>0x0c047fff8020: fa fa 00[fa]fa fa fd fa fa fa fa fa fa fa fa fa
  0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8060: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8070: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==115400==ABORTING

sample.icc.zip

CLI tools do not report underlying IccProfLib version

It would be extremely handy if all the CLI tools reported the version of the underlying IccProfLib as otherwise there is no known way to identify versioning information across multiple instances or from log files. Compile dates are obviously unreliable.

wxProfileDump already has the equivalent in the Help | About dialog.

The simplistic way is adding 2 lines of code to each CLI main program:

#include "IccProfLibVer.h"
...
printf("Built with IccProfLib version " ICCPROFLIBVER "\n");

Or you may prefer to implement as a method.
If you let me know your preference I am happy to make said changes... or you can do.

Supporting internal 8bit encoding for XYZ color space

In IccCmm.cpp, inside the methods CIccCmm::ToInternalEncoding (line 8045) and CIccCmm::FromInternalEncoding (line 8354), an encoding of 8 bits while using the XYZ color space is currently not implemented, I was wondering whether this encoding is possible with the XYZ space or not?
Thanks

version-independent interpretation of bytes 84..99

I noticed that the IccProflib reports an error in v2.x.y profile versions of the ICC profiles if the bytes corresponding to the "Profile ID" of v4.3.0 (bytes 84..99) are not zero and do not correspond to the md5 sum above the ICC header.

However, the spec for v2.x.y states that bytes 84..99 are reserved (see https://www.color.org/ICC_Minor_Revision_for_Web.pdf, page 12).

My question:

Is interpreting bytes 84..99 in v2.x.y profile versions a bug in IccProfLib?
If no, what did I interpret wrong?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.