Coverage Report

Created: 2026-06-30 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/file-jpeg.c
Line
Count
Source
1
/* file-jpeg.c
2
 *
3
 * Routines for JFIF image/jpeg media dissection
4
 * Copyright 2004, Olivier Biot.
5
 *
6
 * Refer to the AUTHORS file or the AUTHORS section in the man page
7
 * for contacting the author(s) of this file.
8
 *
9
 * Wireshark - Network traffic analyzer
10
 * By Gerald Combs <gerald@wireshark.org>
11
 * Copyright 1998 Gerald Combs
12
 *
13
 * JFIF media decoding functionality provided by Olivier Biot.
14
 *
15
 * The JFIF specifications are found at several locations, such as:
16
 * https://www.w3.org/Graphics/JPEG/jfif3.pdf
17
 * https://www.w3.org/Graphics/JPEG/itu-t81.pdf
18
 *
19
 * The Exif specifications are found at several locations, such as:
20
 * https://web.archive.org/web/20080911194340/http://www.exif.org/
21
 * https://www.cipa.jp/e/std/std-sec.html
22
 * https://www.cipa.jp/std/documents/download_e.html?DC-008-Translation-2023-E
23
 *
24
 * SPDX-License-Identifier: GPL-2.0-or-later
25
 */
26
27
#include "config.h"
28
29
#include <epan/packet.h>
30
#include <epan/expert.h>
31
#include <epan/unit_strings.h>
32
#include <wsutil/array.h>
33
#include <wiretap/wtap.h>
34
35
void proto_register_jfif(void);
36
void proto_reg_handoff_jfif(void);
37
38
/* General-purpose debug logger.
39
 * Requires double parentheses because of variable arguments of printf().
40
 *
41
 * Enable debug logging for JFIF by defining AM_CFLAGS
42
 * so that it contains "-DDEBUG_image_jfif" or "-DDEBUG_image"
43
 */
44
#if (defined(DEBUG_image_jfif) || defined(DEBUG_image))
45
#define DebugLog(x) \
46
    g_print("%s:%u: ", __FILE__, __LINE__); \
47
    g_print x
48
#else
49
#define DebugLog(x) ;
50
#endif
51
52
/************************** Variable declarations **************************/
53
54
0
#define MARKER_TEM      0xFF01
55
56
/* 0xFF02 -- 0xFFBF are reserved */
57
58
0
#define MARKER_SOF0     0xFFC0
59
0
#define MARKER_SOF1     0xFFC1
60
0
#define MARKER_SOF2     0xFFC2
61
0
#define MARKER_SOF3     0xFFC3
62
63
#define MARKER_DHT      0xFFC4
64
65
0
#define MARKER_SOF5     0xFFC5
66
0
#define MARKER_SOF6     0xFFC6
67
0
#define MARKER_SOF7     0xFFC7
68
0
#define MARKER_SOF8     0xFFC8
69
0
#define MARKER_SOF9     0xFFC9
70
0
#define MARKER_SOF10    0xFFCA
71
0
#define MARKER_SOF11    0xFFCB
72
73
#define MARKER_DAC      0xFFCC
74
75
0
#define MARKER_SOF13    0xFFCD
76
0
#define MARKER_SOF14    0xFFCE
77
0
#define MARKER_SOF15    0xFFCF
78
79
0
#define MARKER_RST0     0xFFD0
80
#define MARKER_RST1     0xFFD1
81
#define MARKER_RST2     0xFFD2
82
#define MARKER_RST3     0xFFD3
83
#define MARKER_RST4     0xFFD4
84
#define MARKER_RST5     0xFFD5
85
#define MARKER_RST6     0xFFD6
86
0
#define MARKER_RST7     0xFFD7
87
88
112
#define MARKER_SOI      0xFFD8
89
0
#define MARKER_EOI      0xFFD9
90
0
#define MARKER_SOS      0xFFDA
91
#define MARKER_DQT      0xFFDB
92
#define MARKER_DNL      0xFFDC
93
#define MARKER_DRI      0xFFDD
94
#define MARKER_DHP      0xFFDE
95
#define MARKER_EXP      0xFFDF
96
97
0
#define MARKER_APP0     0xFFE0
98
0
#define MARKER_APP1     0xFFE1
99
0
#define MARKER_APP2     0xFFE2
100
#define MARKER_APP3     0xFFE3
101
#define MARKER_APP4     0xFFE4
102
#define MARKER_APP5     0xFFE5
103
#define MARKER_APP6     0xFFE6
104
#define MARKER_APP7     0xFFE7
105
#define MARKER_APP8     0xFFE8
106
#define MARKER_APP9     0xFFE9
107
#define MARKER_APP10    0xFFEA
108
#define MARKER_APP11    0xFFEB
109
#define MARKER_APP12    0xFFEC
110
#define MARKER_APP13    0xFFED
111
#define MARKER_APP14    0xFFEE
112
#define MARKER_APP15    0xFFEF
113
114
#define MARKER_JPG0     0xFFF0
115
#define MARKER_JPG1     0xFFF1
116
#define MARKER_JPG2     0xFFF2
117
#define MARKER_JPG3     0xFFF3
118
#define MARKER_JPG4     0xFFF4
119
#define MARKER_JPG5     0xFFF5
120
#define MARKER_JPG6     0xFFF6
121
#define MARKER_JPG7     0xFFF7
122
#define MARKER_JPG8     0xFFF8
123
#define MARKER_JPG9     0xFFF9
124
#define MARKER_JPG10    0xFFFA
125
#define MARKER_JPG11    0xFFFB
126
#define MARKER_JPG12    0xFFFC
127
#define MARKER_JPG13    0xFFFD
128
129
0
#define MARKER_COM      0xFFFE
130
131
0
#define marker_has_length(marker) ( ! ( \
132
0
       ((marker) == MARKER_TEM) \
133
0
    || ((marker) == MARKER_SOI) \
134
0
    || ((marker) == MARKER_EOI) \
135
0
    || ( ((marker) >= MARKER_RST0) && ((marker) <= MARKER_RST7) ) \
136
0
    ) )
137
138
139
static const value_string vals_marker[] = {
140
    { MARKER_TEM,   "Reserved - For temporary private use in arithmetic coding" },
141
    { MARKER_SOF0,  "Start of Frame (non-differential, Huffman coding) - Baseline DCT" },
142
    { MARKER_SOF1,  "Start of Frame (non-differential, Huffman coding) - Extended sequential DCT" },
143
    { MARKER_SOF2,  "Start of Frame (non-differential, Huffman coding) - Progressive DCT" },
144
    { MARKER_SOF3,  "Start of Frame (non-differential, Huffman coding) - Lossless (sequential)" },
145
    { MARKER_DHT,   "Define Huffman table(s)" },
146
    { MARKER_SOF5,  "Start of Frame (differential, Huffman coding) - Differential sequential DCT" },
147
    { MARKER_SOF6,  "Start of Frame (differential, Huffman coding) - Differential progressive DCT" },
148
    { MARKER_SOF7,  "Start of Frame (differential, Huffman coding) - Differential lossless (sequential)" },
149
    { MARKER_SOF8,  "Start of Frame (non-differential, arithmetic coding) - Reserved for JPEG extensions" },
150
    { MARKER_SOF9,  "Start of Frame (non-differential, arithmetic coding) - Extended sequential DCT" },
151
    { MARKER_SOF10, "Start of Frame (non-differential, arithmetic coding) - Progressive DCT" },
152
    { MARKER_SOF11, "Start of Frame (non-differential, arithmetic coding) - Lossless (sequential)" },
153
    { MARKER_DAC,   "Define arithmetic coding conditioning(s)" },
154
    { MARKER_SOF13, "Start of Frame (differential, arithmetic coding) - Differential sequential DCT" },
155
    { MARKER_SOF14, "Start of Frame (differential, arithmetic coding) - Differential progressive DCT" },
156
    { MARKER_SOF15, "Start of Frame (differential, arithmetic coding) - Differential lossless (sequential)" },
157
    { MARKER_RST0,  "Restart interval termination - Restart with modulo 8 count 0" },
158
    { MARKER_RST1,  "Restart interval termination - Restart with modulo 8 count 1" },
159
    { MARKER_RST2,  "Restart interval termination - Restart with modulo 8 count 2" },
160
    { MARKER_RST3,  "Restart interval termination - Restart with modulo 8 count 3" },
161
    { MARKER_RST4,  "Restart interval termination - Restart with modulo 8 count 4" },
162
    { MARKER_RST5,  "Restart interval termination - Restart with modulo 8 count 5" },
163
    { MARKER_RST6,  "Restart interval termination - Restart with modulo 8 count 6" },
164
    { MARKER_RST7,  "Restart interval termination - Restart with modulo 8 count 7" },
165
    { MARKER_SOI,   "Start of Image" },
166
    { MARKER_EOI,   "End of Image" },
167
    { MARKER_SOS,   "Start of Scan" },
168
    { MARKER_DQT,   "Define quantization table(s)" },
169
    { MARKER_DNL,   "Define number of lines" },
170
    { MARKER_DRI,   "Define restart interval" },
171
    { MARKER_DHP,   "Define hierarchical progression" },
172
    { MARKER_EXP,   "Expand reference component(s)" },
173
    { MARKER_APP0,  "Reserved for application segments - 0" },
174
    { MARKER_APP1,  "Reserved for application segments - 1" },
175
    { MARKER_APP2,  "Reserved for application segments - 2" },
176
    { MARKER_APP3,  "Reserved for application segments - 3" },
177
    { MARKER_APP4,  "Reserved for application segments - 4" },
178
    { MARKER_APP5,  "Reserved for application segments - 5" },
179
    { MARKER_APP6,  "Reserved for application segments - 6" },
180
    { MARKER_APP7,  "Reserved for application segments - 7" },
181
    { MARKER_APP8,  "Reserved for application segments - 8" },
182
    { MARKER_APP9,  "Reserved for application segments - 9" },
183
    { MARKER_APP10, "Reserved for application segments - 10" },
184
    { MARKER_APP11, "Reserved for application segments - 11" },
185
    { MARKER_APP12, "Reserved for application segments - 12" },
186
    { MARKER_APP13, "Reserved for application segments - 13" },
187
    { MARKER_APP14, "Reserved for application segments - 14" },
188
    { MARKER_APP15, "Reserved for application segments - 15" },
189
    { MARKER_JPG0,  "Reserved for JPEG extensions - 0" },
190
    { MARKER_JPG1,  "Reserved for JPEG extensions - 1" },
191
    { MARKER_JPG2,  "Reserved for JPEG extensions - 2" },
192
    { MARKER_JPG3,  "Reserved for JPEG extensions - 3" },
193
    { MARKER_JPG4,  "Reserved for JPEG extensions - 4" },
194
    { MARKER_JPG5,  "Reserved for JPEG extensions - 5" },
195
    { MARKER_JPG6,  "Reserved for JPEG extensions - 6" },
196
    { MARKER_JPG7,  "Reserved for JPEG extensions - 7" },
197
    { MARKER_JPG8,  "Reserved for JPEG extensions - 8" },
198
    { MARKER_JPG9,  "Reserved for JPEG extensions - 9" },
199
    { MARKER_JPG10, "Reserved for JPEG extensions - 10" },
200
    { MARKER_JPG11, "Reserved for JPEG extensions - 11" },
201
    { MARKER_JPG12, "Reserved for JPEG extensions - 12" },
202
    { MARKER_JPG13, "Reserved for JPEG extensions - 13" },
203
    { MARKER_COM,   "Comment" },
204
    { 0x00, NULL }
205
};
206
207
static const value_string vals_units[] = {
208
    { 0, "No units; Xdensity and Ydensity specify the pixel aspect ratio" },
209
    { 1, "Dots per inch" },
210
    { 2, "Dots per centimeter" },
211
    { 0x00, NULL }
212
};
213
214
static const value_string vals_extension_code[] = {
215
    { 0x10, "Thumbnail encoded using JPEG" },
216
    { 0x11, "Thumbnail encoded using 1 byte (8 bits) per pixel" },
217
    { 0x13, "Thumbnail encoded using 3 bytes (24 bits) per pixel" },
218
    { 0x00, NULL }
219
};
220
221
enum {
222
    EXIF_TAG_EXIF_IFD_POINTER = 0x8769,
223
    EXIF_TAG_GPS_IFD_POINTER = 0x8825,
224
    EXIF_TAG_INTEROP_IFD_POINTER = 0xA005,
225
};
226
227
static const value_string vals_ifd_tags[] = {
228
    /*
229
     * Tags related to image data structure:
230
     */
231
    { 0x0100, "ImageWidth" },
232
    { 0x0101, "ImageLength" },
233
    { 0x0102, "BitsPerSample" },
234
    { 0x0103, "Compression" },
235
    { 0x0106, "PhotometricInterpretation" },
236
    { 0x0112, "Orientation" },
237
    { 0x0115, "SamplesPerPixel" },
238
    { 0x011C, "PlanarConfiguration" },
239
    { 0x0212, "YCbCrSubSampling" },
240
    { 0x0213, "YCbCrPositioning" },
241
    { 0x011A, "XResolution" },
242
    { 0x011B, "YResolution" },
243
    { 0x0128, "ResolutionUnit" },
244
    /*
245
     * Tags relating to recording offset:
246
     */
247
    { 0x0111, "StripOffsets" },
248
    { 0x0116, "RowsPerStrip" },
249
    { 0x0117, "StripByteCounts" },
250
    { 0x0201, "JPEGInterchangeFormat" },
251
    { 0x0202, "JPEGInterchangeFormatLength" },
252
    /*
253
     * Tags relating to image data characteristics:
254
     */
255
    { 0x012D, "TransferFunction" },
256
    { 0x013E, "WhitePoint" },
257
    { 0x013F, "PrimaryChromaticities" },
258
    { 0x0211, "YCbCrCoefficients" },
259
    { 0x0214, "ReferenceBlackWhite" },
260
    /*
261
     * Other tags:
262
     */
263
    { 0x0132, "DateTime" },
264
    { 0x010E, "ImageDescription" },
265
    { 0x010F, "Make" },
266
    { 0x0110, "Model" },
267
    { 0x0131, "Software" },
268
    { 0x013B, "Artist" },
269
    { 0x8298, "Copyright" },
270
    /*
271
     * Exif-specific IFD:
272
     */
273
    { EXIF_TAG_EXIF_IFD_POINTER, "Exif IFD Pointer"},
274
    { EXIF_TAG_GPS_IFD_POINTER, "GPS IFD Pointer"},
275
    { EXIF_TAG_INTEROP_IFD_POINTER, "Interoperability IFD Pointer"},
276
277
    { 0x0000, NULL }
278
};
279
280
static const value_string vals_ifd_tags_exif[] = {
281
    /*
282
     * Tags relating to version:
283
     */
284
    { 0x9000, "ExifVersion" },
285
    { 0xA000, "FlashpixVersion" },
286
    /*
287
     * Tags relating to image data characteristics:
288
     */
289
    { 0xA001, "ColorSpace" },
290
    { 0xA500, "Gamma" },
291
    /*
292
     * Tags relating to image configuration:
293
     */
294
    { 0x9101, "ComponentsConfiguration" },
295
    { 0x9102, "CompressedBitsPerPixel" },
296
    { 0xA002, "PixelXDimension" },
297
    { 0xA003, "PixelYDimension" },
298
    /*
299
     * Tags relating to user information:
300
     */
301
    { 0x927C, "MakerNote" },
302
    { 0x9286, "UserComment" },
303
    /*
304
     * Tags relating to related file information:
305
     */
306
    { 0xA004, "RelatedSoundFile" },
307
    /*
308
     * Tags relating to date and time:
309
     */
310
    { 0x9003, "DateTimeOriginal" },
311
    { 0x9004, "DateTimeDigitized" },
312
    { 0x9010, "OffsetTime" },
313
    { 0x9011, "OffsetTimeOriginal" },
314
    { 0x9012, "OffsetTimeDigitized" },
315
    { 0x9290, "SubSecTime" },
316
    { 0x9291, "SubSecTimeOriginal" },
317
    { 0x9292, "SubSecTimeDigitized" },
318
    /*
319
     * Tags relating to picture-taking conditions:
320
     */
321
    { 0x829A, "ExposureTime" },
322
    { 0x829D, "FNumber" },
323
    { 0x8822, "ExposureProgram" },
324
    { 0x8824, "SpectralSensitivity" },
325
    { 0x8827, "PhotographicSensitivity" },
326
    { 0x8828, "OECF" },
327
    { 0x8830, "SensitivityType" },
328
    { 0x8831, "StandardOutputSensitivity" },
329
    { 0x8832, "RecommendedExposureIndex" },
330
    { 0x8833, "ISOSpeed" },
331
    { 0x8834, "ISOSpeedLatitudeyyy" },
332
    { 0x8835, "ISOSpeedLatitudezzz" },
333
    { 0x9201, "ShutterSpeedValue" },
334
    { 0x9202, "ApertureValue" },
335
    { 0x9203, "BrightnessValue" },
336
    { 0x9204, "ExposureBiasValue" },
337
    { 0x9205, "MaxApertureValue" },
338
    { 0x9206, "SubjectDistance" },
339
    { 0x9207, "MeteringMode" },
340
    { 0x9208, "LightSource" },
341
    { 0x9209, "Flash" },
342
    { 0x920A, "FocalLength" },
343
    { 0x9214, "SubjectArea" },
344
    { 0xA20B, "FlashEnergy" },
345
    { 0xA20C, "SpatialFrequencyResponse" },
346
    { 0xA20E, "FocalPlaneXResolution" },
347
    { 0xA20F, "FocalPlaneYResolution" },
348
    { 0xA210, "FocalPlaneResolutionUnit" },
349
    { 0xA214, "SubjectLocation" },
350
    { 0xA215, "ExposureIndex" },
351
    { 0xA217, "SensingMethod" },
352
    { 0xA300, "FileSource" },
353
    { 0xA301, "SceneType" },
354
    { 0xA302, "CFAPattern" },
355
    { 0xA401, "CustomRendered" },
356
    { 0xA402, "ExposureMode" },
357
    { 0xA403, "WhiteBalance" },
358
    { 0xA404, "DigitalZoomRatio" },
359
    { 0xA405, "FocalLengthIn35mmFilm" },
360
    { 0xA406, "SceneCaptureType" },
361
    { 0xA407, "GainControl" },
362
    { 0xA408, "Contrast" },
363
    { 0xA409, "Saturation" },
364
    { 0xA40A, "Sharpness" },
365
    { 0xA40B, "DeviceSettingDescription" },
366
    { 0xA40C, "SubjectDistanceRange" },
367
    { 0xA460, "CompositeImage" },
368
    { 0xA461, "SourceImageNumberOfCompositeImage" },
369
    { 0xA462, "SourceExposureTimesOfCompositeImage" },
370
    /*
371
     * Tags relating to shooting situation:
372
     */
373
    { 0x9400, "Temperature" },
374
    { 0x9401, "Humidity" },
375
    { 0x9402, "Pressure" },
376
    { 0x9403, "WaterDepth" },
377
    { 0x9404, "Acceleration" },
378
    { 0x9405, "CameraElevationAngle" },
379
    /*
380
     * Other tags:
381
     */
382
    { 0xA420, "ImageUniqueID" },
383
    { 0xA430, "CameraOwnerName" },
384
    { 0xA431, "BodySerialNumber" },
385
    { 0xA432, "LensSpecification" },
386
    { 0xA433, "LensMake" },
387
    { 0xA434, "LensModel" },
388
    { 0xA435, "LensSerialNumber" },
389
390
    { 0x0000, NULL }
391
};
392
393
static const value_string vals_ifd_tags_gps[] = {
394
    /*
395
     * Tags relating to GPS:
396
     */
397
    { 0x00, "GPSVersionID" },
398
    { 0x01, "GPSLatitudeRef" },
399
    { 0x02, "GPSLatitude" },
400
    { 0x03, "GPSLongitudeRef" },
401
    { 0x04, "GPSLongitude" },
402
    { 0x05, "GPSAltitudeRef" },
403
    { 0x06, "GPSAltitude" },
404
    { 0x07, "GPSTimeStamp" },
405
    { 0x08, "GPSSatellites" },
406
    { 0x09, "GPSStatus" },
407
    { 0x0A, "GPSMeasureMode" },
408
    { 0x0B, "GPSDOP" },
409
    { 0x0C, "GPSSpeedRef" },
410
    { 0x0D, "GPSSpeed" },
411
    { 0x0E, "GPSTrackRef" },
412
    { 0x0F, "GPSTrack" },
413
    { 0x10, "GPSImgDirectionRef" },
414
    { 0x11, "GPSImgDirection" },
415
    { 0x12, "GPSMapDatum" },
416
    { 0x13, "GPSDestLatitudeRef" },
417
    { 0x14, "GPSDestLatitude" },
418
    { 0x15, "GPSDestLongitudeRef" },
419
    { 0x16, "GPSDestLongitude" },
420
    { 0x17, "GPSDestBearingRef" },
421
    { 0x18, "GPSDestBearing" },
422
    { 0x19, "GPSDestDistanceRef" },
423
    { 0x1A, "GPSDestDistance" },
424
    { 0x1B, "GPSProcessingMethod" },
425
    { 0x1C, "GPSAreaInformation" },
426
    { 0x1D, "GPSDateStamp" },
427
    { 0x1E, "GPSDifferential" },
428
    { 0x1F, "GPSHPositioningError" },
429
    { 0x00, NULL }
430
};
431
432
static const value_string vals_ifd_tags_interop[] = {
433
    /*
434
     * Tags relating to interoperability:
435
     */
436
    { 0x1, "InteroperabilityIndex" },
437
    { 0x0, NULL }
438
};
439
440
enum {
441
    EXIF_TYPE_BYTE      = 0x0001,
442
    EXIF_TYPE_ASCII     = 0x0002,
443
    EXIF_TYPE_SHORT     = 0x0003,
444
    EXIF_TYPE_LONG      = 0x0004,
445
    EXIF_TYPE_RATIONAL  = 0x0005,
446
    /* 0x0006 */
447
    EXIF_TYPE_UNDEFINED = 0x0007,
448
    /* 0x0008 */
449
    EXIF_TYPE_SLONG     = 0x0009,
450
    EXIF_TYPE_SRATIONAL = 0x000A,
451
};
452
453
static const value_string vals_exif_types[] = {
454
    { EXIF_TYPE_BYTE,      "BYTE" },
455
    { EXIF_TYPE_ASCII,     "ASCII" },
456
    { EXIF_TYPE_SHORT,     "SHORT" },
457
    { EXIF_TYPE_LONG,      "LONG" },
458
    { EXIF_TYPE_RATIONAL,  "RATIONAL" },
459
    { EXIF_TYPE_UNDEFINED, "UNDEFINED" },
460
    { EXIF_TYPE_SLONG,     "SLONG" },
461
    { EXIF_TYPE_SRATIONAL, "SRATIONAL" },
462
463
    { 0x0000, NULL }
464
};
465
466
/* Initialize the protocol and registered fields */
467
static int proto_jfif;
468
469
/* Marker */
470
static int hf_marker;
471
/* Marker segment */
472
static int hf_marker_segment;
473
static int hf_len;
474
/* MARKER_APP0 */
475
static int hf_identifier;
476
/* MARKER_APP0 - JFIF */
477
static int hf_version;
478
static int hf_version_major;
479
static int hf_version_minor;
480
static int hf_units;
481
static int hf_xdensity;
482
static int hf_ydensity;
483
static int hf_xthumbnail;
484
static int hf_ythumbnail;
485
static int hf_rgb;
486
/* MARKER_APP0 - JFXX */
487
static int hf_extension_code;
488
/* start of Frame */
489
static int hf_sof_header;
490
static int hf_sof_precision;
491
static int hf_sof_lines;
492
static int hf_sof_samples_per_line;
493
static int hf_sof_nf;
494
static int hf_sof_c_i;
495
static int hf_sof_h_i;
496
static int hf_sof_v_i;
497
static int hf_sof_tq_i;
498
499
/* Start of Scan */
500
static int hf_sos_header;
501
static int hf_sos_ns;
502
static int hf_sos_cs_j;
503
static int hf_sos_td_j;
504
static int hf_sos_ta_j;
505
static int hf_sos_ss;
506
static int hf_sos_se;
507
static int hf_sos_ah;
508
static int hf_sos_al;
509
510
/* Comment */
511
static int hf_comment_header;
512
static int hf_comment;
513
514
static int hf_remain_seg_data;
515
static int hf_endianness;
516
static int hf_start_ifd_offset;
517
static int hf_next_ifd_offset;
518
static int hf_exif_flashpix_marker;
519
static int hf_entropy_coded_segment;
520
static int hf_fill_bytes;
521
static int hf_skipped_tiff_data;
522
static int hf_ifd_num_fields;
523
static int hf_ifd_tag;
524
static int hf_ifd_tag_exif;
525
static int hf_ifd_tag_gps;
526
static int hf_ifd_tag_interop;
527
static int hf_ifd_type;
528
static int hf_ifd_count;
529
static int hf_ifd_offset;
530
static int hf_ifd_value_byte;
531
static int hf_ifd_value_ascii;
532
static int hf_ifd_value_short;
533
static int hf_ifd_value_long;
534
static int hf_ifd_value_rational;
535
static int hf_ifd_value_rational_numerator;
536
static int hf_ifd_value_rational_denominator;
537
static int hf_ifd_value_undefined;
538
static int hf_ifd_value_slong;
539
static int hf_ifd_value_srational;
540
static int hf_ifd_value_srational_numerator;
541
static int hf_ifd_value_srational_denominator;
542
543
544
/* Initialize the subtree pointers */
545
static int ett_jfif;
546
static int ett_marker_segment;
547
static int ett_details;
548
static int ett_ifd;
549
static int ett_rational;
550
static int ett_srational;
551
552
static expert_field ei_file_jpeg_first_identifier_not_jfif;
553
static expert_field ei_start_ifd_offset;
554
static expert_field ei_next_ifd_offset;
555
static expert_field ei_ifd_value_offset;
556
557
/****************** JFIF protocol dissection functions ******************/
558
559
560
/*
561
 * Process a marker segment (with length).
562
 */
563
static void
564
process_marker_segment(proto_tree *tree, tvbuff_t *tvb, uint32_t len,
565
        uint16_t marker, const char *marker_name)
566
0
{
567
0
    proto_item *ti;
568
0
    proto_tree *subtree;
569
570
0
    if (!tree)
571
0
        return;
572
573
0
    ti = proto_tree_add_item(tree, hf_marker_segment,
574
0
            tvb, 0, -1, ENC_NA);
575
0
    subtree = proto_item_add_subtree(ti, ett_marker_segment);
576
577
0
    proto_item_append_text(ti, ": %s (0x%04X)", marker_name, marker);
578
0
    proto_tree_add_item(subtree, hf_marker, tvb, 0, 2, ENC_BIG_ENDIAN);
579
580
0
    proto_tree_add_item(subtree, hf_len, tvb, 2, 2, ENC_BIG_ENDIAN);
581
582
0
    proto_tree_add_bytes_format_value(subtree, hf_remain_seg_data, tvb, 4, -1, NULL, "%u bytes", len - 2);
583
0
}
584
585
/*
586
 * Process a Start of Frame header (with length).
587
 */
588
static void
589
process_sof_header(proto_tree *tree, tvbuff_t *tvb, uint32_t len _U_,
590
        uint16_t marker, const char *marker_name)
591
0
{
592
0
    proto_item *ti;
593
0
    proto_tree *subtree;
594
0
    uint8_t count;
595
0
    uint32_t offset;
596
597
0
    if (!tree)
598
0
        return;
599
600
0
    ti = proto_tree_add_item(tree, hf_sof_header,
601
0
            tvb, 0, -1, ENC_NA);
602
0
    subtree = proto_item_add_subtree(ti, ett_marker_segment);
603
604
0
    proto_item_append_text(ti, ": %s (0x%04X)", marker_name, marker);
605
0
    proto_tree_add_item(subtree, hf_marker, tvb, 0, 2, ENC_BIG_ENDIAN);
606
607
0
    proto_tree_add_item(subtree, hf_len, tvb, 2, 2, ENC_BIG_ENDIAN);
608
609
0
    proto_tree_add_item(subtree, hf_sof_precision, tvb, 4, 1, ENC_BIG_ENDIAN);
610
611
0
    proto_tree_add_item(subtree, hf_sof_lines, tvb, 5, 2, ENC_BIG_ENDIAN);
612
613
0
    proto_tree_add_item(subtree, hf_sof_samples_per_line, tvb, 7, 2, ENC_BIG_ENDIAN);
614
615
0
    proto_tree_add_item(subtree, hf_sof_nf, tvb, 9, 1, ENC_BIG_ENDIAN);
616
0
    count = tvb_get_uint8(tvb, 9);
617
0
    offset = 10;
618
0
    while (count > 0) {
619
0
        proto_tree_add_item(subtree, hf_sof_c_i, tvb, offset++, 1, ENC_BIG_ENDIAN);
620
0
        proto_tree_add_item(subtree, hf_sof_h_i, tvb, offset, 1, ENC_BIG_ENDIAN);
621
0
        proto_tree_add_item(subtree, hf_sof_v_i, tvb, offset++, 1, ENC_BIG_ENDIAN);
622
0
        proto_tree_add_item(subtree, hf_sof_tq_i, tvb, offset++, 1, ENC_BIG_ENDIAN);
623
0
        count--;
624
0
    }
625
0
}
626
627
/*
628
 * Process a Start of Segment header (with length).
629
 */
630
static void
631
process_sos_header(proto_tree *tree, tvbuff_t *tvb, uint32_t len _U_,
632
        uint16_t marker, const char *marker_name)
633
0
{
634
0
    proto_item *ti;
635
0
    proto_tree *subtree;
636
0
    uint8_t count;
637
0
    uint32_t offset;
638
639
0
    if (!tree)
640
0
        return;
641
642
0
    ti = proto_tree_add_item(tree, hf_sos_header,
643
0
            tvb, 0, -1, ENC_NA);
644
0
    subtree = proto_item_add_subtree(ti, ett_marker_segment);
645
646
0
    proto_item_append_text(ti, ": %s (0x%04X)", marker_name, marker);
647
0
    proto_tree_add_item(subtree, hf_marker, tvb, 0, 2, ENC_BIG_ENDIAN);
648
649
0
    proto_tree_add_item(subtree, hf_len, tvb, 2, 2, ENC_BIG_ENDIAN);
650
651
0
    proto_tree_add_item(subtree, hf_sos_ns, tvb, 4, 1, ENC_BIG_ENDIAN);
652
0
    count = tvb_get_uint8(tvb, 4);
653
0
    offset = 5;
654
0
    while (count > 0) {
655
0
        proto_tree_add_item(subtree, hf_sos_cs_j, tvb, offset++, 1, ENC_BIG_ENDIAN);
656
0
        proto_tree_add_item(subtree, hf_sos_td_j, tvb, offset, 1, ENC_BIG_ENDIAN);
657
0
        proto_tree_add_item(subtree, hf_sos_ta_j, tvb, offset++, 1, ENC_BIG_ENDIAN);
658
0
        count--;
659
0
    }
660
661
0
    proto_tree_add_item(subtree, hf_sos_ss, tvb, offset++, 1, ENC_BIG_ENDIAN);
662
0
    proto_tree_add_item(subtree, hf_sos_se, tvb, offset++, 1, ENC_BIG_ENDIAN);
663
664
0
    proto_tree_add_item(subtree, hf_sos_ah, tvb, offset, 1, ENC_BIG_ENDIAN);
665
0
    proto_tree_add_item(subtree, hf_sos_al, tvb, offset, 1, ENC_BIG_ENDIAN);
666
0
    /* offset ++ */;
667
0
}
668
669
/*
670
 * Process a Comment header (with length).
671
 */
672
static void
673
process_comment_header(proto_tree *tree, tvbuff_t *tvb, uint32_t len,
674
        uint16_t marker, const char *marker_name)
675
0
{
676
0
    proto_item *ti;
677
0
    proto_tree *subtree;
678
679
0
    if (!tree)
680
0
        return;
681
682
0
    ti = proto_tree_add_item(tree, hf_comment_header,
683
0
            tvb, 0, -1, ENC_NA);
684
0
    subtree = proto_item_add_subtree(ti, ett_marker_segment);
685
686
0
    proto_item_append_text(ti, ": %s (0x%04X)", marker_name, marker);
687
0
    proto_tree_add_item(subtree, hf_marker, tvb, 0, 2, ENC_BIG_ENDIAN);
688
689
0
    proto_tree_add_item(subtree, hf_len, tvb, 2, 2, ENC_BIG_ENDIAN);
690
691
0
    proto_tree_add_item(subtree, hf_comment, tvb, 4, len-2, ENC_ASCII);
692
0
}
693
694
695
/* Process an APP0 block.
696
 *
697
 * XXX - This code only works on US-ASCII systems!!!
698
 */
699
static int
700
process_app0_segment(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, uint32_t len,
701
        uint16_t marker, const char *marker_name)
702
0
{
703
0
    proto_item *ti;
704
0
    proto_tree *subtree;
705
0
    proto_tree *subtree_details = NULL;
706
0
    uint32_t offset;
707
0
    char *str;
708
0
    unsigned str_size;
709
0
    uint16_t x, y;
710
711
0
    if (!tree)
712
0
        return 0;
713
714
0
    ti = proto_tree_add_item(tree, hf_marker_segment,
715
0
            tvb, 0, -1, ENC_NA);
716
0
    subtree = proto_item_add_subtree(ti, ett_marker_segment);
717
718
0
    proto_item_append_text(ti, ": %s (0x%04X)", marker_name, marker);
719
0
    proto_tree_add_item(subtree, hf_marker, tvb, 0, 2, ENC_BIG_ENDIAN);
720
721
0
    proto_tree_add_item(subtree, hf_len, tvb, 2, 2, ENC_BIG_ENDIAN);
722
723
0
    str = (char *)tvb_get_stringz_enc(pinfo->pool, tvb, 4, &str_size, ENC_ASCII);
724
0
    ti = proto_tree_add_item(subtree, hf_identifier, tvb, 4, str_size, ENC_ASCII);
725
0
    if (strcmp(str, "JFIF") == 0) {
726
        /* Version */
727
0
        ti = proto_tree_add_none_format(subtree, hf_version,
728
0
                tvb, 9, 2, "Version: %u.%u",
729
0
                tvb_get_uint8(tvb, 9),
730
0
                tvb_get_uint8(tvb, 10));
731
0
        subtree_details = proto_item_add_subtree(ti, ett_details);
732
0
        proto_tree_add_item(subtree_details, hf_version_major,
733
0
                tvb, 9, 1, ENC_BIG_ENDIAN);
734
0
        proto_tree_add_item(subtree_details, hf_version_minor,
735
0
                tvb, 10, 1, ENC_BIG_ENDIAN);
736
737
0
        proto_tree_add_item(subtree, hf_units,
738
0
                tvb, 11, 1, ENC_BIG_ENDIAN);
739
740
        /* Aspect ratio */
741
0
        proto_tree_add_item(subtree, hf_xdensity,
742
0
                tvb, 12, 2, ENC_BIG_ENDIAN);
743
0
        proto_tree_add_item(subtree, hf_ydensity,
744
0
                tvb, 14, 2, ENC_BIG_ENDIAN);
745
746
        /* Thumbnail */
747
0
        proto_tree_add_item(subtree, hf_xthumbnail,
748
0
                tvb, 16, 1, ENC_BIG_ENDIAN);
749
0
        proto_tree_add_item(subtree, hf_ythumbnail,
750
0
                tvb, 17, 1, ENC_BIG_ENDIAN);
751
0
        x = tvb_get_uint8(tvb, 16);
752
0
        y = tvb_get_uint8(tvb, 17);
753
0
        if (x || y) {
754
0
            proto_tree_add_item(subtree, hf_rgb,
755
0
                    tvb, 18, 3 * (x * y), ENC_NA);
756
0
            offset = 18 + (3 * (x * y));
757
0
        } else {
758
0
            offset = 18;
759
0
        }
760
0
    }
761
0
    else if (strcmp(str, "JFXX") == 0) {
762
0
        proto_tree_add_item(subtree, hf_extension_code,
763
0
                tvb, 9, 1, ENC_BIG_ENDIAN);
764
        /* XXX - dissect the extension based on its extension code */
765
0
        offset = 10;
766
0
    }
767
0
    else { /* Unknown */
768
0
        proto_item_append_text(ti, " (unknown identifier)");
769
0
        offset = 4 + str_size;
770
771
0
        proto_tree_add_bytes_format_value(subtree, hf_remain_seg_data, tvb, offset, -1, NULL, "%u bytes", len - 2 - str_size);
772
0
    }
773
0
    return offset;
774
0
}
775
776
static void
777
// NOLINTNEXTLINE(misc-no-recursion)
778
process_tiff_ifd_chain(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo,
779
        unsigned encoding, uint32_t start_ifd_offset,
780
        int hf_tag, const char *ifd_type_desc)
781
0
{
782
0
    uint32_t next_ifd_offset = start_ifd_offset;
783
784
0
    for (unsigned ifd_index = 0;; ++ifd_index) {
785
0
        int offset = next_ifd_offset;
786
        /*
787
         * Process the IFD
788
         */
789
0
        uint32_t num_fields = tvb_get_uint16(tvb, offset, encoding);
790
0
        proto_tree *subtree_ifd = proto_tree_add_subtree_format(tree, tvb, offset, num_fields * 12 + 6,
791
0
                ett_ifd, NULL, "%s #%u", ifd_type_desc, ifd_index);
792
0
        proto_tree_add_item(subtree_ifd, hf_ifd_num_fields, tvb, offset, 2, encoding);
793
0
        offset += 2;
794
0
        while (num_fields-- > 0) {
795
0
            uint32_t field_tag, field_type, value_count, value_size;
796
0
            int value_hf;
797
798
0
            proto_tree_add_item_ret_uint(subtree_ifd, hf_tag, tvb, offset, 2, encoding, &field_tag);
799
0
            offset += 2;
800
0
            proto_tree_add_item_ret_uint(subtree_ifd, hf_ifd_type, tvb, offset, 2, encoding, &field_type);
801
0
            offset += 2;
802
0
            proto_tree_add_item_ret_uint(subtree_ifd, hf_ifd_count, tvb, offset, 4, encoding, &value_count);
803
0
            offset += 4;
804
805
0
            switch (field_type) {
806
0
            case EXIF_TYPE_BYTE:
807
0
                value_size = 1; value_hf = hf_ifd_value_byte; break;
808
0
            case EXIF_TYPE_ASCII:
809
0
                value_size = 1; value_hf = hf_ifd_value_ascii; break;
810
0
            case EXIF_TYPE_SHORT:
811
0
                value_size = 2; value_hf = hf_ifd_value_short; break;
812
0
            case EXIF_TYPE_LONG:
813
0
                value_size = 4; value_hf = hf_ifd_value_long; break;
814
0
            case EXIF_TYPE_RATIONAL:
815
0
                value_size = 8; value_hf = hf_ifd_value_rational; break;
816
0
            case EXIF_TYPE_UNDEFINED:
817
0
                value_size = 1; value_hf = hf_ifd_value_undefined; break;
818
0
            case EXIF_TYPE_SLONG:
819
0
                value_size = 4; value_hf = hf_ifd_value_slong; break;
820
0
            case EXIF_TYPE_SRATIONAL:
821
0
                value_size = 8; value_hf = hf_ifd_value_srational; break;
822
0
            default:
823
0
                value_size = 0; value_hf = -1; break;
824
0
            }
825
826
0
            int value_offset = -1;
827
0
            proto_tree *value_parent = NULL;
828
829
0
            if (value_size == 0 || 4 / value_size < value_count) {
830
                /* The value(s) are located outside the IFD, and the offset field points to them. */
831
0
                uint32_t value_offset_uint;
832
0
                proto_item *offset_item = proto_tree_add_item_ret_uint(
833
0
                        subtree_ifd, hf_ifd_offset, tvb, offset, 4, encoding, &value_offset_uint);
834
835
0
                if (value_offset_uint < tvb_reported_length(tvb)) {
836
0
                    value_offset = (int)value_offset_uint;
837
0
                } else {
838
0
                    expert_add_info_format(pinfo, offset_item, &ei_ifd_value_offset,
839
0
                            "bogus, should be < %u", tvb_reported_length(tvb));
840
0
                }
841
842
0
                value_parent = tree;
843
0
            } else {
844
                /* The value(s) are small enough to fit directly in the offset field. */
845
0
                value_offset = offset;
846
0
                value_parent = subtree_ifd;
847
0
            }
848
849
0
            if (value_offset >= 0) {
850
0
                if (value_hf == hf_ifd_value_ascii || value_hf == hf_ifd_value_undefined)
851
0
                    proto_tree_add_item(value_parent, value_hf, tvb, value_offset, value_count, ENC_NA);
852
0
                else if (value_size != 0)
853
0
                    for (uint32_t i = 0; i < value_count; ++i) {
854
0
                        proto_item *value_item = proto_tree_add_item(value_parent, value_hf, tvb,
855
0
                                value_offset, value_size, encoding);
856
857
0
                        if (value_hf == hf_ifd_value_rational) {
858
0
                            proto_tree *subtree_value = proto_item_add_subtree(value_item, ett_rational);
859
0
                            uint32_t num, denom;
860
0
                            proto_tree_add_item_ret_uint(
861
0
                                    subtree_value, hf_ifd_value_rational_numerator, tvb,
862
0
                                    value_offset, 4, encoding, &num);
863
0
                            proto_tree_add_item_ret_uint(
864
0
                                    subtree_value, hf_ifd_value_rational_denominator, tvb,
865
0
                                    value_offset + 4, 4, encoding, &denom);
866
0
                            proto_item_set_text(value_item, "Value: %"PRIu32"/%"PRIu32, num, denom);
867
0
                        }
868
0
                        else if (value_hf == hf_ifd_value_srational) {
869
0
                            proto_tree *subtree_value = proto_item_add_subtree(value_item, ett_srational);
870
0
                            int32_t num, denom;
871
0
                            proto_tree_add_item_ret_int(
872
0
                                    subtree_value, hf_ifd_value_srational_numerator, tvb,
873
0
                                    value_offset, 4, encoding, &num);
874
0
                            proto_tree_add_item_ret_int(
875
0
                                    subtree_value, hf_ifd_value_srational_denominator, tvb,
876
0
                                    value_offset + 4, 4, encoding, &denom);
877
0
                            proto_item_set_text(value_item, "Value: %"PRIi32"/%"PRIi32, num, denom);
878
0
                        }
879
0
                        else if (value_hf == hf_ifd_value_long && value_count == 1 && hf_tag == hf_ifd_tag) {
880
0
                            uint32_t extension_ifd_offset = tvb_get_uint32(tvb, value_offset, encoding);
881
0
                            int extension_hf_ifd_tag = -1;
882
0
                            const char *extension_ifd_type_desc = NULL;
883
884
0
                            switch (field_tag) {
885
0
                            case EXIF_TAG_EXIF_IFD_POINTER:
886
0
                                extension_hf_ifd_tag = hf_ifd_tag_exif;
887
0
                                extension_ifd_type_desc = "Exif IFD";
888
0
                                break;
889
0
                            case EXIF_TAG_GPS_IFD_POINTER:
890
0
                                extension_hf_ifd_tag = hf_ifd_tag_gps;
891
0
                                extension_ifd_type_desc = "GPS IFD";
892
0
                                break;
893
0
                            case EXIF_TAG_INTEROP_IFD_POINTER:
894
0
                                extension_hf_ifd_tag = hf_ifd_tag_interop;
895
0
                                extension_ifd_type_desc = "Interoperability IFD";
896
0
                                break;
897
0
                            }
898
899
0
                            if (extension_ifd_type_desc) {
900
0
                                if (extension_ifd_offset < tvb_reported_length(tvb)) {
901
0
                                    increment_dissection_depth(pinfo);
902
0
                                    process_tiff_ifd_chain(tree, tvb, pinfo, encoding,
903
0
                                            extension_ifd_offset, extension_hf_ifd_tag,
904
0
                                            extension_ifd_type_desc);
905
0
                                    decrement_dissection_depth(pinfo);
906
0
                                } else {
907
0
                                    expert_add_info_format(pinfo, value_item, &ei_start_ifd_offset,
908
0
                                        "bogus, should be < %u", tvb_reported_length(tvb));
909
0
                                }
910
0
                            }
911
0
                        }
912
913
0
                        value_offset += value_size;
914
0
                    }
915
0
            }
916
0
            offset += 4;
917
0
        }
918
        /*
919
         * Offset to the next IFD
920
         */
921
0
        proto_item *next_ifd_offset_item = proto_tree_add_item_ret_uint(
922
0
                subtree_ifd, hf_next_ifd_offset, tvb, offset, 4, encoding, &next_ifd_offset);
923
0
        offset += 4;
924
925
0
        if (next_ifd_offset == 0)
926
0
            break;
927
928
0
        if (next_ifd_offset < (uint32_t)offset) {
929
0
            expert_add_info_format(pinfo, next_ifd_offset_item, &ei_next_ifd_offset,
930
0
                    " (bogus, should be >= %u)", offset);
931
0
            return;
932
0
        }
933
934
0
        if (tvb_reported_length_remaining(tvb, next_ifd_offset) < 6) {
935
            /* At minimum the next IFD offset should have room for a 2-byte
936
             * count of # of fields and a 4-byte offset to the next IFD.
937
             * This might indicate a missing offset to the next IFD, e.g.,
938
             * in a Exif IFD or similar. (See #20355).
939
             */
940
0
            expert_add_info_format(pinfo, next_ifd_offset_item, &ei_next_ifd_offset,
941
0
                    " (bogus, should be <= %u)", tvb_reported_length_remaining(tvb, 6));
942
0
            return;
943
0
        }
944
0
    }
945
0
}
946
947
static void
948
process_tiff(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo)
949
0
{
950
    /*
951
     * Endianness
952
     */
953
0
    unsigned encoding;
954
0
    int offset = 0;
955
956
0
    uint16_t byte_order = tvb_get_ntohs(tvb, offset);
957
0
    if (byte_order == 0x4949) {
958
0
        encoding = ENC_LITTLE_ENDIAN;
959
0
        proto_tree_add_uint_format_value(tree, hf_endianness, tvb, offset, 2, byte_order, "little endian");
960
0
    } else if (byte_order == 0x4D4D) {
961
0
        encoding = ENC_BIG_ENDIAN;
962
0
        proto_tree_add_uint_format_value(tree, hf_endianness, tvb, offset, 2, byte_order, "big endian");
963
0
    } else {
964
        /* Error: invalid endianness encoding */
965
0
        proto_tree_add_uint_format_value(tree, hf_endianness, tvb, offset, 2, byte_order,
966
0
                "Incorrect encoding 0x%04x- skipping the remainder of this application marker", byte_order);
967
0
        return;
968
0
    }
969
0
    offset += 2;
970
    /*
971
     * Fixed value 42 = 0x002a
972
     */
973
0
    offset += 2;
974
    /*
975
     * Offset to IFD
976
     */
977
0
    uint32_t start_ifd_offset;
978
0
    proto_item* start_ifd_offset_item = proto_tree_add_item_ret_uint(
979
0
            tree, hf_start_ifd_offset, tvb, offset, 4, encoding, &start_ifd_offset);
980
0
    offset += 4;
981
    /*
982
     * Check for a bogus offset value.
983
     * XXX - bogus value message should also deal with a
984
     * value that's too large and causes an overflow.
985
     * Or should it just check against the segment length,
986
     * which is 16 bits?
987
     */
988
0
    if (start_ifd_offset < (uint32_t)offset) {
989
0
        expert_add_info_format(pinfo, start_ifd_offset_item, &ei_start_ifd_offset,
990
0
                " (bogus, should be >= %u)", offset);
991
0
        return;
992
0
    }
993
994
0
    process_tiff_ifd_chain(tree, tvb, pinfo, encoding, start_ifd_offset,
995
0
            hf_ifd_tag, "Image File Directory");
996
0
}
997
998
/* Process an APP1 block.
999
 *
1000
 * XXX - This code only works on US-ASCII systems!!!
1001
 */
1002
static void
1003
process_app1_segment(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, uint32_t len,
1004
        uint16_t marker, const char *marker_name, bool show_first_identifier_not_jfif)
1005
0
{
1006
0
    proto_item *ti;
1007
0
    proto_tree *subtree;
1008
0
    char *str;
1009
0
    unsigned str_size;
1010
0
    int offset = 0;
1011
1012
0
    ti = proto_tree_add_item(tree, hf_marker_segment,
1013
0
            tvb, 0, -1, ENC_NA);
1014
0
    subtree = proto_item_add_subtree(ti, ett_marker_segment);
1015
1016
0
    proto_item_append_text(ti, ": %s (0x%04X)", marker_name, marker);
1017
0
    proto_tree_add_item(subtree, hf_marker, tvb, offset, 2, ENC_BIG_ENDIAN);
1018
0
    offset += 2;
1019
1020
0
    proto_tree_add_item(subtree, hf_len, tvb, offset, 2, ENC_BIG_ENDIAN);
1021
0
    offset += 2;
1022
1023
0
    str = (char*)tvb_get_stringz_enc(pinfo->pool, tvb, offset, &str_size, ENC_ASCII);
1024
0
    ti = proto_tree_add_item(subtree, hf_identifier, tvb, offset, str_size, ENC_ASCII);
1025
0
    offset += str_size;
1026
1027
0
    if (show_first_identifier_not_jfif && strcmp(str, "JFIF") != 0) {
1028
0
        expert_add_info(pinfo, ti, &ei_file_jpeg_first_identifier_not_jfif);
1029
0
    }
1030
1031
0
    if (strcmp(str, "Exif") == 0) {
1032
0
        offset++; /* Skip a byte supposed to be 0x00 */
1033
1034
0
        tvbuff_t *tvb_tiff = tvb_new_subset_remaining(tvb, offset);
1035
0
        process_tiff(subtree, tvb_tiff, pinfo);
1036
0
    } else {
1037
0
        proto_tree_add_bytes_format_value(subtree, hf_remain_seg_data, tvb, offset, -1, NULL, "%u bytes", len - 2 - str_size);
1038
0
        proto_item_append_text(ti, " (Unknown identifier)");
1039
0
    }
1040
0
}
1041
1042
/* Process an APP2 block.
1043
 *
1044
 * XXX - This code only works on US-ASCII systems!!!
1045
 */
1046
static void
1047
process_app2_segment(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, uint32_t len,
1048
        uint16_t marker, const char *marker_name)
1049
0
{
1050
0
    proto_item *ti;
1051
0
    proto_tree *subtree;
1052
0
    char *str;
1053
0
    unsigned str_size;
1054
1055
0
    if (!tree)
1056
0
        return;
1057
1058
0
    ti = proto_tree_add_item(tree, hf_marker_segment,
1059
0
            tvb, 0, -1, ENC_NA);
1060
0
    subtree = proto_item_add_subtree(ti, ett_marker_segment);
1061
1062
0
    proto_item_append_text(ti, ": %s (0x%04X)", marker_name, marker);
1063
0
    proto_tree_add_item(subtree, hf_marker, tvb, 0, 2, ENC_BIG_ENDIAN);
1064
1065
0
    proto_tree_add_item(subtree, hf_len, tvb, 2, 2, ENC_BIG_ENDIAN);
1066
1067
0
    str = (char*)tvb_get_stringz_enc(pinfo->pool, tvb, 4, &str_size, ENC_ASCII);
1068
0
    ti = proto_tree_add_item(subtree, hf_identifier, tvb, 4, str_size, ENC_ASCII);
1069
0
    if (strcmp(str, "FPXR") == 0) {
1070
0
        proto_tree_add_item(tree, hf_exif_flashpix_marker, tvb, 0, -1, ENC_NA);
1071
0
    } else {
1072
0
        proto_tree_add_bytes_format_value(subtree, hf_remain_seg_data, tvb, 4 + str_size, -1, NULL, "%u bytes", len - 2 - str_size);
1073
0
        proto_item_append_text(ti, " (Unknown identifier)");
1074
0
    }
1075
0
}
1076
1077
static int
1078
dissect_jfif(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1079
142
{
1080
142
    proto_tree *subtree;
1081
142
    proto_item *ti;
1082
142
    unsigned tvb_len = tvb_reported_length(tvb);
1083
142
    uint32_t start_entropy = 0;
1084
142
    uint32_t start_fill, start_marker;
1085
142
    bool show_first_identifier_not_jfif = false;
1086
1087
    /* check if we have a full JFIF in tvb */
1088
142
    if (tvb_len < 20)
1089
30
        return 0;
1090
    /* Start Of Image marker must come first */
1091
112
    if (tvb_get_ntohs(tvb, 0) != MARKER_SOI)
1092
112
        return 0;
1093
    /* Check identifier field in first App segment is "JFIF", although "Exif" from App1
1094
       can/does appear here too... */
1095
0
    if (tvb_memeql(tvb, 6, (const uint8_t*)"Exif", 5) == 0) {
1096
0
        show_first_identifier_not_jfif = true;
1097
0
    }
1098
0
    else if (tvb_memeql(tvb, 6, (const uint8_t*)"JFIF", 5)) {
1099
0
        return 0;
1100
0
    }
1101
1102
    /* Add summary to INFO column if it is enabled */
1103
0
    col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "(JPEG JFIF image)");
1104
1105
0
    ti = proto_tree_add_item(tree, proto_jfif,
1106
0
            tvb, 0, -1, ENC_NA);
1107
0
    subtree = proto_item_add_subtree(ti, ett_jfif);
1108
1109
0
    for (; ; ) {
1110
0
        const char *str;
1111
0
        uint16_t marker;
1112
0
        bool start_fill_found;
1113
1114
0
        start_fill = start_entropy;
1115
1116
0
        for (; ; ) {
1117
0
            start_fill_found = tvb_find_uint8_remaining(tvb, start_fill, 0xFF, &start_fill);
1118
1119
0
            if (start_fill_found == false || tvb_len - start_fill == 1
1120
0
              || tvb_get_uint8(tvb, start_fill + 1) != 0) /* FF 00 is FF escaped */
1121
0
                break;
1122
1123
0
            start_fill += 2;
1124
0
        }
1125
1126
0
        if (start_fill_found == false) {
1127
0
            start_fill = tvb_len;
1128
0
        }
1129
1130
0
        if (start_fill != start_entropy)
1131
0
            proto_tree_add_item(subtree, hf_entropy_coded_segment, tvb, start_entropy, start_fill - start_entropy, ENC_NA);
1132
1133
0
        if (start_fill == tvb_len) break;
1134
1135
0
        start_marker = start_fill;
1136
1137
0
        while (tvb_get_uint8(tvb, start_marker + 1) == 0xFF)
1138
0
            ++start_marker;
1139
1140
0
        if (start_marker != start_fill)
1141
0
            proto_tree_add_item(subtree, hf_fill_bytes, tvb, start_fill, start_marker - start_fill, ENC_NA);
1142
1143
0
        marker = tvb_get_ntohs(tvb, start_marker);
1144
0
        str = try_val_to_str(marker, vals_marker);
1145
0
        if (str) { /* Known marker */
1146
0
            if (marker_has_length(marker)) { /* Marker segment */
1147
                /* Length of marker segment = 2 + len */
1148
0
                const uint16_t len = tvb_get_ntohs(tvb, start_marker + 2);
1149
0
                tvbuff_t *tmp_tvb = tvb_new_subset_length(tvb, start_marker, 2 + len);
1150
0
                switch (marker) {
1151
0
                    case MARKER_APP0:
1152
0
                        process_app0_segment(subtree, tmp_tvb, pinfo, len, marker, str);
1153
0
                        break;
1154
0
                    case MARKER_APP1:
1155
0
                        process_app1_segment(subtree, tmp_tvb, pinfo, len, marker, str, show_first_identifier_not_jfif);
1156
0
                        show_first_identifier_not_jfif = false;
1157
0
                        break;
1158
0
                    case MARKER_APP2:
1159
0
                        process_app2_segment(subtree, tmp_tvb, pinfo, len, marker, str);
1160
0
                        break;
1161
0
                    case MARKER_SOF0:
1162
0
                    case MARKER_SOF1:
1163
0
                    case MARKER_SOF2:
1164
0
                    case MARKER_SOF3:
1165
0
                    case MARKER_SOF5:
1166
0
                    case MARKER_SOF6:
1167
0
                    case MARKER_SOF7:
1168
0
                    case MARKER_SOF8:
1169
0
                    case MARKER_SOF9:
1170
0
                    case MARKER_SOF10:
1171
0
                    case MARKER_SOF11:
1172
0
                    case MARKER_SOF13:
1173
0
                    case MARKER_SOF14:
1174
0
                    case MARKER_SOF15:
1175
0
                        process_sof_header(subtree, tmp_tvb, len, marker, str);
1176
0
                        break;
1177
0
                    case MARKER_SOS:
1178
0
                        process_sos_header(subtree, tmp_tvb, len, marker, str);
1179
0
                        break;
1180
0
                    case MARKER_COM:
1181
0
                        process_comment_header(subtree, tmp_tvb, len, marker, str);
1182
0
                        break;
1183
0
                    default:
1184
0
                        process_marker_segment(subtree, tmp_tvb, len, marker, str);
1185
0
                        break;
1186
0
                }
1187
0
                start_entropy = start_marker + 2 + len;
1188
0
            } else { /* Marker but no segment */
1189
                /* Length = 2 */
1190
0
                proto_tree_add_item(subtree, hf_marker,
1191
0
                        tvb, start_marker, 2, ENC_BIG_ENDIAN);
1192
0
                start_entropy = start_marker + 2;
1193
0
            }
1194
0
        } else { /* Reserved! */
1195
0
            ti = proto_tree_add_item(subtree, hf_marker,
1196
0
                    tvb, start_marker, 2, ENC_BIG_ENDIAN);
1197
0
            proto_item_append_text(ti, " (Reserved)");
1198
0
            return tvb_len;
1199
0
        }
1200
0
    }
1201
1202
0
    return tvb_len;
1203
0
}
1204
1205
static bool
1206
dissect_jfif_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1207
133
{
1208
133
    return dissect_jfif(tvb, pinfo, tree, data) > 0;
1209
133
}
1210
1211
/****************** Register the protocol with Wireshark ******************/
1212
1213
void
1214
proto_register_jfif(void)
1215
14
{
1216
    /*
1217
     * Setup list of header fields.
1218
     */
1219
14
    static hf_register_info hf[] = {
1220
        /* Marker */
1221
14
        { &hf_marker,
1222
14
          {   "Marker",
1223
14
              "image-jfif.marker",
1224
14
              FT_UINT16, BASE_HEX, VALS(vals_marker), 0x0,
1225
14
              "JFIF Marker",
1226
14
              HFILL
1227
14
          }
1228
14
        },
1229
        /* Marker segment */
1230
14
        { &hf_marker_segment,
1231
14
          {   "Marker segment",
1232
14
              "image-jfif.marker_segment",
1233
14
              FT_NONE, BASE_NONE, NULL, 0x0,
1234
14
              NULL,
1235
14
              HFILL
1236
14
          }
1237
14
        },
1238
14
        { &hf_len,
1239
14
          {   "Length",
1240
14
              "image-jfif.length",
1241
14
              FT_UINT16, BASE_DEC, 0, 0x0,
1242
14
              "Length of segment (including length field)",
1243
14
              HFILL
1244
14
          }
1245
14
        },
1246
        /* MARKER_APP0 */
1247
14
        { &hf_identifier,
1248
14
          {   "Identifier",
1249
14
              "image-jfif.identifier",
1250
14
              FT_STRINGZ, BASE_NONE, NULL, 0x0,
1251
14
              "Identifier of the segment",
1252
14
              HFILL
1253
14
          }
1254
14
        },
1255
        /* MARKER_APP0 - JFIF */
1256
14
        { &hf_version,
1257
14
          {   "Version",
1258
14
              "image-jfif.version",
1259
14
              FT_NONE, BASE_NONE, NULL, 0x0,
1260
14
              "JFIF Version",
1261
14
              HFILL
1262
14
          }
1263
14
        },
1264
14
        { &hf_version_major,
1265
14
          {   "Major Version",
1266
14
              "image-jfif.version.major",
1267
14
              FT_UINT8, BASE_DEC, NULL, 0x0,
1268
14
              "JFIF Major Version",
1269
14
              HFILL
1270
14
          }
1271
14
        },
1272
14
        { &hf_version_minor,
1273
14
          {   "Minor Version",
1274
14
              "image-jfif.version.minor",
1275
14
              FT_UINT8, BASE_DEC, NULL, 0x0,
1276
14
              "JFIF Minor Version",
1277
14
              HFILL
1278
14
          }
1279
14
        },
1280
14
        { &hf_units,
1281
14
          {   "Units",
1282
14
              "image-jfif.units",
1283
14
              FT_UINT8, BASE_DEC, VALS(vals_units), 0x0,
1284
14
              "Units used in this segment",
1285
14
              HFILL
1286
14
          }
1287
14
        },
1288
14
        { &hf_xdensity,
1289
14
          {   "Xdensity",
1290
14
              "image-jfif.Xdensity",
1291
14
              FT_UINT16, BASE_DEC, NULL, 0x0,
1292
14
              "Horizontal pixel density",
1293
14
              HFILL
1294
14
          }
1295
14
        },
1296
14
        { &hf_ydensity,
1297
14
          {   "Ydensity",
1298
14
              "image-jfif.Ydensity",
1299
14
              FT_UINT16, BASE_DEC, NULL, 0x0,
1300
14
              "Vertical pixel density",
1301
14
              HFILL
1302
14
          }
1303
14
        },
1304
14
        { &hf_xthumbnail,
1305
14
          {   "Xthumbnail",
1306
14
              "image-jfif.Xthumbnail",
1307
14
              FT_UINT16, BASE_DEC, NULL, 0x0,
1308
14
              "Thumbnail horizontal pixel count",
1309
14
              HFILL
1310
14
          }
1311
14
        },
1312
14
        { &hf_ythumbnail,
1313
14
          {   "Ythumbnail",
1314
14
              "image-jfif.Ythumbnail",
1315
14
              FT_UINT16, BASE_DEC, NULL, 0x0,
1316
14
              "Thumbnail vertical pixel count",
1317
14
              HFILL
1318
14
          }
1319
14
        },
1320
14
        { &hf_rgb,
1321
14
          {   "RGB values of thumbnail pixels",
1322
14
              "image-jfif.RGB",
1323
14
              FT_BYTES, BASE_NONE, NULL, 0x0,
1324
14
              "RGB values of the thumbnail pixels (24 bit per pixel, Xthumbnail x Ythumbnail pixels)",
1325
14
              HFILL
1326
14
          }
1327
14
        },
1328
        /* MARKER_APP0 - JFXX */
1329
14
        { &hf_extension_code,
1330
14
          {   "Extension code",
1331
14
              "image-jfif.extension.code",
1332
14
              FT_UINT8, BASE_HEX, VALS(vals_extension_code), 0x0,
1333
14
              "JFXX extension code for thumbnail encoding",
1334
14
              HFILL
1335
14
          }
1336
14
        },
1337
        /* Header: Start of Frame (MARKER_SOF) */
1338
14
        { &hf_sof_header,
1339
14
          {   "Start of Frame header",
1340
14
              "image-jfif.sof",
1341
14
              FT_NONE, BASE_NONE, NULL, 0x0,
1342
14
              NULL,
1343
14
              HFILL
1344
14
          }
1345
14
        },
1346
14
        { &hf_sof_precision,
1347
14
          {   "Sample Precision (bits)",
1348
14
              "image-jfif.sof.precision",
1349
14
              FT_UINT8, BASE_DEC, NULL, 0x0,
1350
14
              "Specifies the precision in bits for the samples of the components in the frame.",
1351
14
              HFILL
1352
14
          }
1353
14
        },
1354
14
        { &hf_sof_lines,
1355
14
          {   "Lines",
1356
14
              "image-jfif.sof.lines",
1357
14
              FT_UINT16, BASE_DEC, NULL, 0x0,
1358
14
              "Specifies the maximum number of lines in the source image.",
1359
14
              HFILL
1360
14
          }
1361
14
        },
1362
14
        { &hf_sof_samples_per_line,
1363
14
          {   "Samples per line",
1364
14
              "image-jfif.sof.samples_per_line",
1365
14
              FT_UINT16, BASE_DEC, NULL, 0x0,
1366
14
              "Specifies the maximum number of samples per line in the source image.",
1367
14
              HFILL
1368
14
          }
1369
14
        },
1370
14
        { &hf_sof_nf,
1371
14
          {   "Number of image components in frame",
1372
14
              "image-jfif.sof.nf",
1373
14
              FT_UINT8, BASE_DEC, NULL, 0x0,
1374
14
              "Specifies the number of source image components in the frame.",
1375
14
              HFILL
1376
14
          }
1377
14
        },
1378
14
        { &hf_sof_c_i,
1379
14
          {   "Component identifier",
1380
14
              "image-jfif.sof.c_i",
1381
14
              FT_UINT8, BASE_DEC, NULL, 0x0,
1382
14
              "Assigns a unique label to the ith component in the sequence of frame component specification parameters.",
1383
14
              HFILL
1384
14
          }
1385
14
        },
1386
14
        { &hf_sof_h_i,
1387
14
          {   "Horizontal sampling factor",
1388
14
              "image-jfif.sof.h_i",
1389
14
              FT_UINT8, BASE_DEC, NULL, 0xF0,
1390
14
              "Specifies the relationship between the component horizontal dimension and maximum image dimension X.",
1391
14
              HFILL
1392
14
          }
1393
14
        },
1394
14
        { &hf_sof_v_i,
1395
14
          {   "Vertical sampling factor",
1396
14
              "image-jfif.sof.v_i",
1397
14
              FT_UINT8, BASE_DEC, NULL, 0x0F,
1398
14
              "Specifies the relationship between the component vertical dimension and maximum image dimension Y.",
1399
14
              HFILL
1400
14
          }
1401
14
        },
1402
14
        { &hf_sof_tq_i,
1403
14
          {   "Quantization table destination selector",
1404
14
              "image-jfif.sof.tq_i",
1405
14
              FT_UINT8, BASE_DEC, NULL, 0x0,
1406
14
              "Specifies one of four possible quantization table destinations from which the quantization table to"
1407
14
              " use for dequantization of DCT coefficients of component Ci is retrieved.",
1408
14
              HFILL
1409
14
          }
1410
14
        },
1411
1412
        /* Header: Start of Segment (MARKER_SOS) */
1413
14
        { &hf_sos_header,
1414
14
          {   "Start of Segment header",
1415
14
              "image-jfif.header.sos",
1416
14
              FT_NONE, BASE_NONE, NULL, 0x0,
1417
14
              NULL,
1418
14
              HFILL
1419
14
          }
1420
14
        },
1421
14
        { &hf_sos_ns,
1422
14
          {   "Number of image components in scan",
1423
14
              "image-jfif.sos.ns",
1424
14
              FT_UINT8, BASE_DEC, NULL, 0x0,
1425
14
              "Specifies the number of source image components in the scan.",
1426
14
              HFILL
1427
14
          }
1428
14
        },
1429
14
        { &hf_sos_cs_j,
1430
14
          {   "Scan component selector",
1431
14
              "image-jfif.sos.component_selector",
1432
14
              FT_UINT8, BASE_DEC, NULL, 0x0,
1433
14
              "Selects which of the Nf image components specified in the frame parameters shall be the jth"
1434
14
              " component in the scan.",
1435
14
              HFILL
1436
14
          }
1437
14
        },
1438
14
        { &hf_sos_td_j,
1439
14
          {   "DC entropy coding table destination selector",
1440
14
              "image-jfif.sos.dc_entropy_selector",
1441
14
              FT_UINT8, BASE_DEC, NULL, 0xF0,
1442
14
              "Specifies one of four possible DC entropy coding table destinations from which the entropy"
1443
14
              " table needed for decoding of the DC coefficients of component Csj is retrieved.",
1444
14
              HFILL
1445
14
          }
1446
14
        },
1447
14
        { &hf_sos_ta_j,
1448
14
          {   "AC entropy coding table destination selector",
1449
14
              "image-jfif.sos.ac_entropy_selector",
1450
14
              FT_UINT8, BASE_DEC, NULL, 0x0F,
1451
14
              "Specifies one of four possible AC entropy coding table destinations from which the entropy"
1452
14
              " table needed for decoding of the AC coefficients of component Csj is retrieved.",
1453
14
              HFILL
1454
14
          }
1455
14
        },
1456
14
        { &hf_sos_ss,
1457
14
          {   "Start of spectral or predictor selection",
1458
14
              "image-jfif.sos.ss",
1459
14
              FT_UINT8, BASE_DEC, NULL, 0x0,
1460
14
              "In the DCT modes of operation, this parameter specifies the first DCT coefficient in"
1461
14
              " each block in zig-zag order which shall be coded in the scan. This parameter shall"
1462
14
              " be set to zero for the sequential DCT processes. In the lossless mode of operations"
1463
14
              " this parameter is used to select the predictor.",
1464
14
              HFILL
1465
14
          }
1466
14
        },
1467
14
        { &hf_sos_se,
1468
14
          {   "End of spectral selection",
1469
14
              "image-jfif.sos.se",
1470
14
              FT_UINT8, BASE_DEC, NULL, 0x0,
1471
14
              "Specifies the last DCT coefficient in each block in zig-zag order which shall be coded"
1472
14
              " in the scan. This parameter shall be set to 63 for the sequential DCT processes. In the"
1473
14
              " lossless mode of operations this parameter has no meaning. It shall be set to zero.",
1474
14
              HFILL
1475
14
          }
1476
14
        },
1477
14
        { &hf_sos_ah,
1478
14
          {   "Successive approximation bit position high",
1479
14
              "image-jfif.sos.ah",
1480
14
              FT_UINT8, BASE_DEC, NULL, 0xF0,
1481
14
              "This parameter specifies the point transform used in the preceding scan (i.e. successive"
1482
14
              " approximation bit position low in the preceding scan) for the band of coefficients"
1483
14
              " specified by Ss and Se. This parameter shall be set to zero for the first scan of each"
1484
14
              " band of coefficients. In the lossless mode of operations this parameter has no meaning."
1485
14
              " It shall be set to zero.",
1486
14
              HFILL
1487
14
          }
1488
14
        },
1489
14
        { &hf_sos_al,
1490
14
          {   "Successive approximation bit position low or point transform",
1491
14
              "image-jfif.sos.al",
1492
14
              FT_UINT8, BASE_DEC, NULL, 0x0F,
1493
14
              "In the DCT modes of operation this parameter specifies the point transform, i.e. bit"
1494
14
              " position low, used before coding the band of coefficients specified by Ss and Se."
1495
14
              " This parameter shall be set to zero for the sequential DCT processes. In the lossless"
1496
14
              " mode of operations, this parameter specifies the point transform, Pt.",
1497
14
              HFILL
1498
14
          }
1499
14
        },
1500
1501
        /* Header: Comment (MARKER_COM) */
1502
14
        { &hf_comment_header,
1503
14
          {   "Comment header",
1504
14
              "image-jfif.header.comment",
1505
14
              FT_NONE, BASE_NONE, NULL, 0x0,
1506
14
              NULL,
1507
14
              HFILL
1508
14
          }
1509
14
        },
1510
14
        { &hf_comment,
1511
14
          {   "Comment",
1512
14
              "image-jfif.comment",
1513
14
              FT_STRING, BASE_NONE, NULL, 0x0,
1514
14
              NULL,
1515
14
              HFILL
1516
14
          }
1517
14
        },
1518
14
        { &hf_remain_seg_data,
1519
14
          {   "Remaining segment data",
1520
14
              "image-jfif.remain_seg_data",
1521
14
              FT_BYTES, BASE_NONE, NULL, 0x0,
1522
14
              NULL,
1523
14
              HFILL
1524
14
          }
1525
14
        },
1526
14
        { &hf_endianness,
1527
14
          {   "Endianness",
1528
14
              "image-jfif.endianness",
1529
14
              FT_UINT16, BASE_HEX, NULL, 0x0,
1530
14
              NULL,
1531
14
              HFILL
1532
14
          }
1533
14
        },
1534
14
        { &hf_start_ifd_offset,
1535
14
          {   "Start offset of IFD starting from the TIFF header start",
1536
14
              "image-jfif.start_ifd_offset",
1537
14
              FT_UINT32, BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes), 0x0,
1538
14
              NULL,
1539
14
              HFILL
1540
14
          }
1541
14
        },
1542
14
        { &hf_next_ifd_offset,
1543
14
          {   "Offset to next IFD from start of TIFF header",
1544
14
              "image-jfif.next_ifd_offset",
1545
14
              FT_UINT32, BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes), 0x0,
1546
14
              NULL,
1547
14
              HFILL
1548
14
          }
1549
14
        },
1550
14
        { &hf_exif_flashpix_marker,
1551
14
          {   "Exif FlashPix APP2 application marker",
1552
14
              "image-jfif.exif_flashpix_marker",
1553
14
              FT_NONE, BASE_NONE, NULL, 0x0,
1554
14
              NULL,
1555
14
              HFILL
1556
14
          }
1557
14
        },
1558
14
        { &hf_entropy_coded_segment,
1559
14
          {   "Entropy-coded segment (dissection is not yet implemented)",
1560
14
              "image-jfif.entropy_coded_segment",
1561
14
              FT_BYTES, BASE_NONE, NULL, 0x0,
1562
14
              NULL,
1563
14
              HFILL
1564
14
          }
1565
14
        },
1566
14
        { &hf_fill_bytes,
1567
14
          {   "Fill bytes",
1568
14
              "image-jfif.fill_bytes",
1569
14
              FT_BYTES, BASE_NONE, NULL, 0x0,
1570
14
              NULL,
1571
14
              HFILL
1572
14
          }
1573
14
        },
1574
14
        { &hf_skipped_tiff_data,
1575
14
          {   "Skipped data between end of TIFF header and start of IFD",
1576
14
              "image-jfif.skipped_tiff_data",
1577
14
              FT_BYTES, BASE_NONE, NULL, 0x0,
1578
14
              NULL,
1579
14
              HFILL
1580
14
          }
1581
14
        },
1582
14
        { &hf_ifd_num_fields,
1583
14
          {   "Number of fields in this IFD",
1584
14
              "image-jfif.ifd.num_fields",
1585
14
              FT_UINT16, BASE_DEC, NULL, 0x0,
1586
14
              NULL,
1587
14
              HFILL
1588
14
          }
1589
14
        },
1590
14
        { &hf_ifd_tag,
1591
14
          {   "Tag",
1592
14
              "image-jfif.ifd.tag",
1593
14
              FT_UINT16, BASE_DEC, VALS(vals_ifd_tags), 0x0,
1594
14
              NULL,
1595
14
              HFILL
1596
14
          }
1597
14
        },
1598
14
        { &hf_ifd_tag_exif,
1599
14
          {   "Tag",
1600
14
              "image-jfif.ifd.tag_exif",
1601
14
              FT_UINT16, BASE_DEC, VALS(vals_ifd_tags_exif), 0x0,
1602
14
              NULL,
1603
14
              HFILL
1604
14
          }
1605
14
        },
1606
14
        { &hf_ifd_tag_gps,
1607
14
          {   "Tag",
1608
14
              "image-jfif.ifd.tag_gps",
1609
14
              FT_UINT16, BASE_DEC, VALS(vals_ifd_tags_gps), 0x0,
1610
14
              NULL,
1611
14
              HFILL
1612
14
          }
1613
14
        },
1614
14
        { &hf_ifd_tag_interop,
1615
14
          {   "Tag",
1616
14
              "image-jfif.ifd.tag_interop",
1617
14
              FT_UINT16, BASE_DEC, VALS(vals_ifd_tags_interop), 0x0,
1618
14
              NULL,
1619
14
              HFILL
1620
14
          }
1621
14
        },
1622
14
        { &hf_ifd_type,
1623
14
          {   "Type",
1624
14
              "image-jfif.ifd.type",
1625
14
              FT_UINT16, BASE_DEC, VALS(vals_exif_types), 0x0,
1626
14
              NULL,
1627
14
              HFILL
1628
14
          }
1629
14
        },
1630
14
        { &hf_ifd_count,
1631
14
          {   "Count",
1632
14
              "image-jfif.ifd.count",
1633
14
              FT_UINT32, BASE_DEC, NULL, 0x0,
1634
14
              NULL,
1635
14
              HFILL
1636
14
          }
1637
14
        },
1638
14
        { &hf_ifd_offset,
1639
14
          {   "Value offset from start of TIFF header",
1640
14
              "image-jfif.ifd.offset",
1641
14
              FT_UINT32, BASE_DEC, NULL, 0x0,
1642
14
              NULL,
1643
14
              HFILL
1644
14
          }
1645
14
        },
1646
14
        { &hf_ifd_value_byte,
1647
14
          {   "Value",
1648
14
              "image-jfif.ifd.value_byte",
1649
14
              FT_UINT8, BASE_DEC, NULL, 0x0,
1650
14
              NULL,
1651
14
              HFILL
1652
14
          }
1653
14
        },
1654
14
        { &hf_ifd_value_ascii,
1655
14
          {   "Value",
1656
14
              "image-jfif.ifd.value_ascii",
1657
14
              FT_STRING, BASE_NONE, NULL, 0x0,
1658
14
              NULL,
1659
14
              HFILL
1660
14
          }
1661
14
        },
1662
14
        { &hf_ifd_value_short,
1663
14
          {   "Value",
1664
14
              "image-jfif.ifd.value_short",
1665
14
              FT_UINT16, BASE_DEC, NULL, 0x0,
1666
14
              NULL,
1667
14
              HFILL
1668
14
          }
1669
14
        },
1670
14
        { &hf_ifd_value_long,
1671
14
          {   "Value",
1672
14
              "image-jfif.ifd.value_long",
1673
14
              FT_UINT32, BASE_DEC, NULL, 0x0,
1674
14
              NULL,
1675
14
              HFILL
1676
14
          }
1677
14
        },
1678
14
        { &hf_ifd_value_rational,
1679
14
          {   "Value",
1680
14
              "image-jfif.ifd.value_rational",
1681
14
              FT_NONE, BASE_NONE, NULL, 0x0,
1682
14
              NULL,
1683
14
              HFILL
1684
14
          }
1685
14
        },
1686
14
        { &hf_ifd_value_rational_numerator,
1687
14
          {   "Numerator",
1688
14
              "image-jfif.ifd.value_rational.numerator",
1689
14
              FT_UINT32, BASE_DEC, NULL, 0x0,
1690
14
              NULL,
1691
14
              HFILL
1692
14
          }
1693
14
        },
1694
14
        { &hf_ifd_value_rational_denominator,
1695
14
          {   "Denominator",
1696
14
              "image-jfif.ifd.value_rational.denominator",
1697
14
              FT_UINT32, BASE_DEC, NULL, 0x0,
1698
14
              NULL,
1699
14
              HFILL
1700
14
          }
1701
14
        },
1702
14
        { &hf_ifd_value_undefined,
1703
14
          {   "Value (raw)",
1704
14
              "image-jfif.ifd.value_undefined",
1705
14
              FT_BYTES, BASE_NONE, NULL, 0x0,
1706
14
              NULL,
1707
14
              HFILL
1708
14
          }
1709
14
        },
1710
14
        { &hf_ifd_value_slong,
1711
14
          {   "Value",
1712
14
              "image-jfif.ifd.value_slong",
1713
14
              FT_INT32, BASE_DEC, NULL, 0x0,
1714
14
              NULL,
1715
14
              HFILL
1716
14
          }
1717
14
        },
1718
14
        { &hf_ifd_value_srational,
1719
14
          {   "Value",
1720
14
              "image-jfif.ifd.value_srational",
1721
14
              FT_NONE, BASE_NONE, NULL, 0x0,
1722
14
              NULL,
1723
14
              HFILL
1724
14
          }
1725
14
        },
1726
14
        { &hf_ifd_value_srational_numerator,
1727
14
          {   "Numerator",
1728
14
              "image-jfif.ifd.value_srational.numerator",
1729
14
              FT_INT32, BASE_DEC, NULL, 0x0,
1730
14
              NULL,
1731
14
              HFILL
1732
14
          }
1733
14
        },
1734
14
        { &hf_ifd_value_srational_denominator,
1735
14
          {   "Denominator",
1736
14
              "image-jfif.ifd.value_srational.denominator",
1737
14
              FT_INT32, BASE_DEC, NULL, 0x0,
1738
14
              NULL,
1739
14
              HFILL
1740
14
          }
1741
14
        },
1742
14
    };
1743
1744
    /* Setup protocol subtree array */
1745
14
    static int *ett[] = {
1746
14
        &ett_jfif,
1747
14
        &ett_marker_segment,
1748
14
        &ett_details,
1749
14
        &ett_ifd,
1750
14
        &ett_rational,
1751
14
        &ett_srational,
1752
14
    };
1753
1754
14
    static ei_register_info ei[] = {
1755
14
        { &ei_file_jpeg_first_identifier_not_jfif,
1756
14
          { "image-jfif.app0-identifier-not-jfif", PI_PROTOCOL, PI_WARN,
1757
14
            "Initial App0 segment with \"JFIF\" Identifier not found", EXPFILL }},
1758
14
        { &ei_start_ifd_offset,
1759
14
          { "image-jfif.start_ifd_offset.invalid", PI_PROTOCOL, PI_WARN,
1760
14
            "Invalid value", EXPFILL }},
1761
14
        { &ei_next_ifd_offset,
1762
14
          { "image-jfif.next_ifd_offset.invalid", PI_PROTOCOL, PI_WARN,
1763
14
            "Invalid value", EXPFILL }},
1764
14
        { &ei_ifd_value_offset,
1765
14
          { "image-jfif.ifd_value_offset.invalid", PI_PROTOCOL, PI_WARN,
1766
14
            "Invalid value", EXPFILL }},
1767
14
    };
1768
1769
14
    expert_module_t* expert_jfif;
1770
1771
    /* Register the protocol name and description */
1772
14
    proto_jfif = proto_register_protocol("JPEG File Interchange Format", "JFIF (JPEG) image", "image-jfif");
1773
1774
    /* Required function calls to register the header fields
1775
     * and subtrees used */
1776
14
    proto_register_field_array(proto_jfif, hf, array_length(hf));
1777
14
    proto_register_subtree_array(ett, array_length(ett));
1778
1779
14
    expert_jfif = expert_register_protocol(proto_jfif);
1780
14
    expert_register_field_array(expert_jfif, ei, array_length(ei));
1781
1782
14
    register_dissector("image-jfif", dissect_jfif, proto_jfif);
1783
14
}
1784
1785
1786
void
1787
proto_reg_handoff_jfif(void)
1788
14
{
1789
14
    dissector_handle_t jfif_handle = find_dissector("image-jfif");
1790
1791
    /* Register the JPEG media type */
1792
14
    dissector_add_string("media_type", "image/jfif", jfif_handle);
1793
14
    dissector_add_string("media_type", "image/jpg", jfif_handle);
1794
14
    dissector_add_string("media_type", "image/jpeg", jfif_handle);
1795
1796
14
    dissector_add_uint("wtap_encap", WTAP_ENCAP_JPEG_JFIF, jfif_handle);
1797
1798
14
    heur_dissector_add("http", dissect_jfif_heur, "JPEG file in HTTP", "jfif_http", proto_jfif, HEURISTIC_ENABLE);
1799
14
    heur_dissector_add("wtap_file", dissect_jfif_heur, "JPEG file", "jfif_wtap", proto_jfif, HEURISTIC_ENABLE);
1800
14
}
1801
1802
/*
1803
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1804
 *
1805
 * Local variables:
1806
 * c-basic-offset: 4
1807
 * tab-width: 8
1808
 * indent-tabs-mode: nil
1809
 * End:
1810
 *
1811
 * vi: set shiftwidth=4 tabstop=8 expandtab:
1812
 * :indentSize=4:tabSize=8:noTabs=true:
1813
 */