Bug Summary

File:Tools/CmdLine/IccDumpProfile/iccDumpProfile.cpp
Warning:line 252, column 9
Value stored to 'pad' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-apple-macosx14.0.0 -Wundef-prefix=TARGET_OS_ -Werror=undef-prefix -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name iccDumpProfile.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=osx -analyzer-checker=security.insecureAPI.decodeValueOfObjCType -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -ffp-contract=on -fno-rounding-math -funwind-tables=2 -target-sdk-version=14.0 -fcompatibility-qualified-id-block-type-checking -fvisibility-inlines-hidden-static-local-var -target-cpu penryn -tune-cpu generic -debugger-tuning=lldb -target-linker-version 1015.7 -fprofile-instrument=clang -fcoverage-mapping -fcoverage-compilation-dir=/Users/xss/DemoIccMAX-hoyt-master/build/Tools/IccDumpProfile -resource-dir /usr/local/Cellar/llvm/17.0.3/lib/clang/17 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.0.sdk -I /Users/xss/DemoIccMAX-hoyt-master/build/Cmake/../../IccProfLib -I /Library/Developer/CommandLineTools/SDKs/MacOSX12.sdk/usr/include/libxml2 -I /Users/xss/DemoIccMAX-hoyt-master/build/Cmake/../../IccXML/IccLibXML -internal-isystem /usr/local/Cellar/llvm/17.0.3/bin/../include/c++/v1 -internal-isystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.0.sdk/usr/local/include -internal-isystem /usr/local/Cellar/llvm/17.0.3/lib/clang/17/include -internal-externc-isystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.0.sdk/usr/include -std=gnu++17 -fdeprecated-macro -fdebug-compilation-dir=/Users/xss/DemoIccMAX-hoyt-master/build/Tools/IccDumpProfile -ferror-limit 19 -fsanitize=address -fsanitize-system-ignorelist=/usr/local/Cellar/llvm/17.0.3/lib/clang/17/share/asan_ignorelist.txt -fno-sanitize-memory-param-retval -fsanitize-address-use-after-scope -fsanitize-address-globals-dead-stripping -fno-assume-sane-operator-new -stack-protector 1 -fblocks -fencode-extended-block-signature -fregister-global-dtors-with-atexit -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -fmax-type-align=16 -analyzer-output=html -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /var/folders/l9/sd9kj1px4yq2wc5_lkwhlt6w0000gn/T/scan-build-2023-10-28-102616-57860-1 -x c++ /Users/xss/DemoIccMAX-hoyt-master/Tools/CmdLine/IccDumpProfile/iccDumpProfile.cpp
1/*
2 File: CmdDumpProfile.cpp
3
4 Contains: Console app to parse and display profile contents
5
6 Version: V1
7
8 Copyright: (c) see below
9*/
10
11/*
12 * The ICC Software License, Version 0.2
13 *
14 *
15 * Copyright (c) 2003-2012 The International Color Consortium. All rights
16 * reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 *
22 * 1. Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 *
25 * 2. Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in
27 * the documentation and/or other materials provided with the
28 * distribution.
29 *
30 * 3. In the absence of prior written permission, the names "ICC" and "The
31 * International Color Consortium" must not be used to imply that the
32 * ICC organization endorses or promotes products derived from this
33 * software.
34 *
35 *
36 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39 * DISCLAIMED. IN NO EVENT SHALL THE INTERNATIONAL COLOR CONSORTIUM OR
40 * ITS CONTRIBUTING MEMBERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47 * SUCH DAMAGE.
48 * ====================================================================
49 *
50 * This software consists of voluntary contributions made by many
51 * individuals on behalf of the The International Color Consortium.
52 *
53 *
54 * Membership in the ICC is encouraged when this software is used for
55 * commercial purposes.
56 *
57 *
58 * For more information on The International Color Consortium, please
59 * see <http://www.color.org/>.
60 *
61 *
62 */
63
64//////////////////////////////////////////////////////////////////////
65// HISTORY:
66//
67// -Initial implementation by Max Derhak 5-15-2003
68//
69//////////////////////////////////////////////////////////////////////
70
71
72#include <stdio.h>
73#include <cstring>
74#include "IccProfile.h"
75#include "IccTag.h"
76#include "IccUtil.h"
77
78void DumpTag(CIccProfile *pIcc, icTagSignature sig)
79{
80 CIccTag *pTag = pIcc->FindTag(sig);
81 char buf[64];
82 CIccInfo Fmt;
83
84 std::string contents;
85
86 if (pTag) {
87 printf("\nContents of %s tag (%s)\n", Fmt.GetTagSigName(sig), icGetSig(buf, sig));
88 printf("Type: ");
89 if (pTag->IsArrayType()) {
90 printf("Array of ");
91 }
92 printf("%s\n", Fmt.GetTagTypeSigName(pTag->GetType()));
93 pTag->Describe(contents);
94 fwrite(contents.c_str(), contents.length(), 1, stdout__stdoutp);
95 }
96 else {
97 printf("Tag (%s) not found in profile\n", icGetSig(buf, sig));
98 }
99}
100
101int main(int argc, char* argv[])
102{
103 int nArg = 1;
104
105 if (argc<=1) {
106print_usage:
107 printf("Usage: iccDumpProfile {-v} profile {tagId to dump/\"ALL\"}\n");
108 printf("\nThe -v option causes profile validation to be performed.\n");
109 return -1;
110 }
111
112 CIccProfile *pIcc;
113 std::string sReport;
114 icValidateStatus nStatus = icValidateOK;
115 bool bDumpValidation = false;
116
117 if (!strncmp(argv[1], "-V", 2) || !strncmp(argv[1], "-v", 2)) {
118 if (argc<=2)
119 goto print_usage;
120
121 nArg = 2;
122
123 pIcc = ValidateIccProfile(argv[nArg], sReport, nStatus);
124 bDumpValidation = true;
125 }
126 else
127 pIcc = OpenIccProfile(argv[nArg]);
128
129 if (!pIcc) {
130 printf("Unable to open '%s'\n", argv[nArg]);
131 }
132 else {
133 icHeader *pHdr = &pIcc->m_Header;
134 CIccInfo Fmt;
135 char buf[64];
136
137 printf("Profile: '%s'\n", argv[nArg]);
138 if(Fmt.IsProfileIDCalculated(&pHdr->profileID))
139 printf("Profile ID: %s\n", Fmt.GetProfileID(&pHdr->profileID));
140 else
141 printf("Profile ID: Profile ID not calculated.\n");
142 printf("Size: %d(0x%x) bytes\n", pHdr->size, pHdr->size);
143
144 printf("\nHeader\n");
145 printf( "------\n");
146 printf("Attributes: %s\n", Fmt.GetDeviceAttrName(pHdr->attributes));
147 printf("Cmm: %s\n", Fmt.GetCmmSigName((icCmmSignature)(pHdr->cmmId)));
148 printf("Creation Date: %d/%d/%d %02u:%02u:%02u\n",
149 pHdr->date.month, pHdr->date.day, pHdr->date.year,
150 pHdr->date.hours, pHdr->date.minutes, pHdr->date.seconds);
151 printf("Creator: %s\n", icGetSig(buf, pHdr->creator));
152 printf("Data Color Space: %s\n", Fmt.GetColorSpaceSigName(pHdr->colorSpace));
153 printf("Flags %s\n", Fmt.GetProfileFlagsName(pHdr->flags));
154 printf("PCS Color Space: %s\n", Fmt.GetColorSpaceSigName(pHdr->pcs));
155 printf("Platform: %s\n", Fmt.GetPlatformSigName(pHdr->platform));
156 printf("Rendering Intent: %s\n", Fmt.GetRenderingIntentName((icRenderingIntent)(pHdr->renderingIntent)));
157 printf("Profile Class: %s\n", Fmt.GetProfileClassSigName(pHdr->deviceClass));
158 if (pHdr->deviceSubClass)
159 printf("Profile SubClass: %s\n", icGetSig(buf, pHdr->deviceSubClass));
160 else
161 printf("Profile SubClass: Not Defined\n");
162 printf("Version: %s\n", Fmt.GetVersionName(pHdr->version));
163 if (pHdr->version >= icVersionNumberV50x05000000 && pHdr->deviceSubClass) {
164 printf("SubClass Version: %s\n", Fmt.GetSubClassVersionName(pHdr->version));
165 }
166 printf("Illuminant: X=%.4lf, Y=%.4lf, Z=%.4lf\n",
167 icFtoD(pHdr->illuminant.X),
168 icFtoD(pHdr->illuminant.Y),
169 icFtoD(pHdr->illuminant.Z));
170 printf("Spectral PCS: %s\n", Fmt.GetSpectralColorSigName(pHdr->spectralPCS));
171 if (pHdr->spectralRange.start || pHdr->spectralRange.end || pHdr->spectralRange.steps) {
172 printf("Spectral PCS Range: start=%.1fnm, end=%.1fnm, steps=%d\n",
173 icF16toF(pHdr->spectralRange.start),
174 icF16toF(pHdr->spectralRange.end),
175 pHdr->spectralRange.steps);
176 }
177 else {
178 printf("Spectral PCS Range: Not Defined\n");
179 }
180
181 if (pHdr->biSpectralRange.start || pHdr->biSpectralRange.end || pHdr->biSpectralRange.steps) {
182 printf("BiSpectral Range: start=%.1fnm, end=%.1fnm, steps=%d\n",
183 icF16toF(pHdr->biSpectralRange.start),
184 icF16toF(pHdr->biSpectralRange.end),
185 pHdr->biSpectralRange.steps);
186 }
187 else {
188 printf("BiSpectral Range: Not Defined\n");
189 }
190 if (pHdr->mcs) {
191 printf("MCS Color Space: %s\n", Fmt.GetColorSpaceSigName((icColorSpaceSignature)pHdr->mcs));
192 }
193 else {
194 printf("MCS Color Space: Not Defined\n");
195 }
196
197 printf("\nProfile Tags\n");
198 printf( "------------\n");
199
200 printf("%28s ID %8s\t%8s\t%8s\n", "Tag", "Offset", "Size", "Pad");
201 printf("%28s ------ %8s\t%8s\t%8s\n", "----", "------", "----", "---");
202
203 int n, closest, pad;
204 TagEntryList::iterator i, j;
205
206 // n is number of Tags in Tag Table
207 for (n=0, i=pIcc->m_Tags->begin(); i!=pIcc->m_Tags->end(); i++, n++) {
208 // Find closest tag after this tag, by scanning all offsets of other tags
209 closest = pHdr->size;
210 for (j = pIcc->m_Tags->begin(); j != pIcc->m_Tags->end(); j++) {
211 if ((i != j) && (j->TagInfo.offset >= i->TagInfo.offset + i->TagInfo.size) && ((int)j->TagInfo.offset <= closest)) {
212 closest = j->TagInfo.offset;
213 }
214 }
215 // Number of actual padding bytes between this tag and closest neighbour (or EOF)
216 // Should be 0-3 if compliant. Negative number if tags overlap!
217 pad = closest - i->TagInfo.offset - i->TagInfo.size;
218
219 printf("%28s %s %8d\t%8d\t%8d\n", Fmt.GetTagSigName(i->TagInfo.sig),
220 icGetSig(buf, i->TagInfo.sig, false), i->TagInfo.offset, i->TagInfo.size, pad);
221 }
222
223 printf("\n");
224
225 // Check additional details if doing detailed validation:
226 // - First tag data offset is immediately after the Tag Table
227 // - Tag data offsets are all 4-byte aligned
228 // - Tag data should be tightly abutted with adjacent tags (or the end of the Tag Table)
229 // (note that tag data can be reused by multiple tags and tags do NOT have to be order)
230 // - Last tag also has to be padded and thus file size is always a multiple of 4. See clause
231 // 7.2.1, bullet (c) of ICC.1:2010 and ICC.2:2019 specs.
232 // - Tag offset + Tag Size should never go beyond EOF
233 // - Multiple tags can reuse data and this is NOT reported as it is perfectly valid and
234 // occurs in real-world ICC profiles
235 // - Tags with overlapping tag data are considered highly suspect (but officially valid)
236 // - 1-3 padding bytes after each tag's data need to be all zero *** NOT DONE - TODO ***
237 if (bDumpValidation) {
238 char str[256];
239 int rndup, smallest_offset = pHdr->size;
240
241 // File size is required to be a multiple of 4 bytes according to clause 7.2.1 bullet (c):
242 // "all tagged element data, including the last, shall be padded by no more than three
243 // following pad bytes to reach a 4 - byte boundary"
244 if (pHdr->size % 4 != 0) {
245 sReport += icMsgValidateNonCompliant;
246 sReport += "File size is not a multiple of 4 bytes (last tag needs padding?).\r\n";
247 nStatus = icMaxStatus(nStatus, icValidateNonCompliant);
248 }
249
250 for (i=pIcc->m_Tags->begin(); i!=pIcc->m_Tags->end(); i++) {
251 rndup = 4 * ((i->TagInfo.size + 3) / 4); // Round up to a 4-byte aligned size as per ICC spec
252 pad = rndup - i->TagInfo.size; // Optimal smallest number of bytes of padding for this tag (0-3)
Value stored to 'pad' is never read
253
254 // Is the Tag offset + Tag Size beyond EOF?
255 if (i->TagInfo.offset + i->TagInfo.size > pHdr->size) {
256 sReport += icMsgValidateNonCompliant;
257 sprintf(str, "Tag %s (offset %d, size %d) ends beyond EOF.\r\n",
258 Fmt.GetTagSigName(i->TagInfo.sig), i->TagInfo.offset, i->TagInfo.size);
259 sReport += str;
260 nStatus = icMaxStatus(nStatus, icValidateNonCompliant);
261 }
262
263 // Is it the first tag data in the file?
264 if ((int)i->TagInfo.offset < smallest_offset) {
265 smallest_offset = (int)i->TagInfo.offset;
266 }
267
268 // Find closest tag after this tag, by scanning all other tag offsets
269 closest = pHdr->size;
270 for (j=pIcc->m_Tags->begin(); j!=pIcc->m_Tags->end(); j++) {
271 if ((i!=j) && (j->TagInfo.offset > i->TagInfo.offset) && ((int)j->TagInfo.offset <= closest)) {
272 closest = j->TagInfo.offset;
273 }
274 }
275
276 // Check if closest tag after this tag is less than offset+size - in which case it overlaps! Ignore last tag.
277 if ((closest < (int)i->TagInfo.offset + (int)i->TagInfo.size) && (closest < (int)pHdr->size)) {
278 sReport += icMsgValidateWarning;
279 sprintf(str, "Tag %s (offset %d, size %d) overlaps with following tag data starting at offset %d.\r\n",
280 Fmt.GetTagSigName(i->TagInfo.sig), i->TagInfo.offset, i->TagInfo.size, closest);
281 sReport += str;
282 nStatus = icMaxStatus(nStatus, icValidateWarning);
283 }
284
285 // Check for gaps between tag data (accounting for 4-byte alignment)
286 if (closest > (int)i->TagInfo.offset + rndup) {
287 sReport += icMsgValidateWarning;
288 sprintf(str, "Tag %s (size %d) is followed by %d unnecessary additional bytes (from offset %d).\r\n",
289 Fmt.GetTagSigName(i->TagInfo.sig), i->TagInfo.size, closest-(i->TagInfo.offset+rndup), (i->TagInfo.offset+rndup));
290 sReport += str;
291 nStatus = icMaxStatus(nStatus, icValidateWarning);
292 }
293 }
294
295 // Clause 7.2.1, bullet (b): "the first set of tagged element data shall immediately follow the tag table"
296 // 1st tag offset should be = Header (128) + Tag Count (4) + Tag Table (n*12)
297 if ((n > 0) && (smallest_offset > 128 + 4 + (n * 12))) {
298 sReport += icMsgValidateNonCompliant;
299 sprintf(str, "First tag data is at offset %d rather than immediately after tag table (offset %d).\r\n",
300 smallest_offset, 128 + 4 + (n * 12));
301 sReport += str;
302 nStatus = icMaxStatus(nStatus, icValidateNonCompliant);
303 }
304 }
305
306 if (argc>nArg+1) {
307 if (!stricmpstrcasecmp(argv[nArg+1], "ALL")) {
308 for (i=pIcc->m_Tags->begin(); i!=pIcc->m_Tags->end(); i++) {
309 DumpTag(pIcc, i->TagInfo.sig);
310 }
311 }
312 else {
313 DumpTag(pIcc, (icTagSignature)icGetSigVal(argv[nArg+1]));
314 }
315 }
316 }
317
318 int nValid = 0;
319
320 if (bDumpValidation) {
321 printf("\nValidation Report\n");
322 printf( "-----------------\n");
323 switch (nStatus) {
324 case icValidateOK:
325 printf("Profile is valid\n\n");
326 break;
327 case icValidateWarning:
328 printf("Profile has warning(s)\n\n");
329 break;
330 case icValidateNonCompliant:
331 printf("Profile violates ICC specification\n\n");
332 break;
333 case icValidateCriticalError:
334 printf("Profile has Critical Error(s) that violate ICC specification.\n\n");
335 nValid = -1;
336 break;
337 default:
338 printf("Profile has unknown status.\n\n");
339 nValid = -2;
340 break;
341 }
342 fwrite(sReport.c_str(), sReport.length(), 1, stdout__stdoutp);
343 }
344
345 delete pIcc;
346
347 return nValid;
348}
349