Coverage Report

Created: 2026-09-28 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/file-png.c
Line
Count
Source
1
/* file-png.c
2
 *
3
 * Routines for PNG (Portable Network Graphics) image file dissection
4
 *
5
 * Copyright 2006 Ronnie Sahlberg
6
 *
7
 * Wireshark - Network traffic analyzer
8
 * By Gerald Combs <gerald@wireshark.org>
9
 * Copyright 1998 Gerald Combs
10
 *
11
 * SPDX-License-Identifier: GPL-2.0-or-later
12
 */
13
/* See http://www.w3.org/TR/PNG for specification
14
 */
15
#include "config.h"
16
17
#include <epan/packet.h>
18
#include <epan/expert.h>
19
#include <epan/tfs.h>
20
#include <wsutil/array.h>
21
22
0
#define MAKE_TYPE_VAL(a, b, c, d)   ((a)<<24 | (b)<<16 | (c)<<8 | (d))
23
24
0
#define CHUNK_TYPE_IHDR   MAKE_TYPE_VAL('I', 'H', 'D', 'R')
25
0
#define CHUNK_TYPE_bKGD   MAKE_TYPE_VAL('b', 'K', 'G', 'D')
26
0
#define CHUNK_TYPE_gAMA   MAKE_TYPE_VAL('g', 'A', 'M', 'A')
27
#define CHUNK_TYPE_iCCP   MAKE_TYPE_VAL('i', 'C', 'C', 'P')
28
0
#define CHUNK_TYPE_cHRM   MAKE_TYPE_VAL('c', 'H', 'R', 'M')
29
0
#define CHUNK_TYPE_pHYs   MAKE_TYPE_VAL('p', 'H', 'Y', 's')
30
#define CHUNK_TYPE_iTXt   MAKE_TYPE_VAL('i', 'T', 'X', 't')
31
0
#define CHUNK_TYPE_tEXt   MAKE_TYPE_VAL('t', 'E', 'X', 't')
32
#define CHUNK_TYPE_sBIT   MAKE_TYPE_VAL('s', 'B', 'I', 'T')
33
0
#define CHUNK_TYPE_sRGB   MAKE_TYPE_VAL('s', 'R', 'G', 'B')
34
0
#define CHUNK_TYPE_tIME   MAKE_TYPE_VAL('t', 'I', 'M', 'E')
35
#define CHUNK_TYPE_IDAT   MAKE_TYPE_VAL('I', 'D', 'A', 'T')
36
#define CHUNK_TYPE_IEND   MAKE_TYPE_VAL('I', 'E', 'N', 'D')
37
#define CHUNK_TYPE_tRNS   MAKE_TYPE_VAL('t', 'R', 'N', 'S')
38
#define CHUNK_TYPE_PLTE   MAKE_TYPE_VAL('P', 'L', 'T', 'E')
39
40
static const value_string chunk_types[] = {
41
    { CHUNK_TYPE_IHDR, "Image Header" },
42
    { CHUNK_TYPE_bKGD, "Background colour" },
43
    { CHUNK_TYPE_gAMA, "Image gamma" },
44
    { CHUNK_TYPE_iCCP, "Embedded ICC profile" },
45
    { CHUNK_TYPE_cHRM, "Primary chromaticities and white point" },
46
    { CHUNK_TYPE_pHYs, "Physical pixel dimensions" },
47
    { CHUNK_TYPE_iTXt, "International textual data" },
48
    { CHUNK_TYPE_tEXt, "Textual data" },
49
    { CHUNK_TYPE_sBIT, "Significant bits" },
50
    { CHUNK_TYPE_sRGB, "Standard RGB colour space" },
51
    { CHUNK_TYPE_tIME, "Image last-modification time" },
52
    { CHUNK_TYPE_IDAT, "Image data chunk" },
53
    { CHUNK_TYPE_IEND, "Image Trailer" },
54
    { CHUNK_TYPE_tRNS, "Transparency" },
55
    { CHUNK_TYPE_PLTE, "Palette" },
56
    { 0, NULL }
57
};
58
59
60
void proto_register_png(void);
61
void proto_reg_handoff_png(void);
62
63
static const true_false_string png_chunk_anc = {
64
    "This is an ANCILLARY chunk",
65
    "This is a CRITICAL chunk"
66
};
67
68
static const true_false_string png_chunk_priv = {
69
    "This is a PRIVATE chunk",
70
    "This is a PUBLIC chunk"
71
};
72
73
static const true_false_string png_chunk_stc = {
74
    "This chunk is SAFE TO COPY",
75
    "This chunk is NOT safe to copy"
76
};
77
78
static const value_string colour_type_vals[] = {
79
    { 0,    "Greyscale"},
80
    { 2,    "Truecolour"},
81
    { 3,    "Indexed-colour"},
82
    { 4,    "Greyscale with alpha"},
83
    { 6,    "Truecolour with alpha"},
84
    { 0, NULL }
85
};
86
87
static const value_string compression_method_vals[] = {
88
    { 0,    "Deflate"},
89
    { 0, NULL }
90
};
91
92
static const value_string filter_method_vals[] = {
93
    { 0,    "Adaptive"},
94
    { 0, NULL }
95
};
96
97
static const value_string interlace_method_vals[] = {
98
    { 0,    "No interlace"},
99
    { 1,    "Adam7"},
100
    { 0, NULL }
101
};
102
103
static const value_string srgb_intent_vals[] = {
104
    { 0, "Perceptual" },
105
    { 1, "Relative colorimetric" },
106
    { 2, "Saturation" },
107
    { 3, "Absolute colorimetric" },
108
    { 0, NULL }
109
};
110
111
static const value_string phys_unit_vals[] = {
112
    { 0,    "Unit is unknown"},
113
    { 1,    "Unit is METRE"},
114
    { 0, NULL }
115
};
116
117
static int proto_png;
118
119
static int hf_png_bkgd_blue;
120
static int hf_png_bkgd_green;
121
static int hf_png_bkgd_greyscale;
122
static int hf_png_bkgd_palette_index;
123
static int hf_png_bkgd_red;
124
static int hf_png_chrm_blue_x;
125
static int hf_png_chrm_blue_y;
126
static int hf_png_chrm_green_x;
127
static int hf_png_chrm_green_y;
128
static int hf_png_chrm_red_x;
129
static int hf_png_chrm_red_y;
130
static int hf_png_chrm_white_x;
131
static int hf_png_chrm_white_y;
132
static int hf_png_chunk_crc;
133
static int hf_png_chunk_data;
134
static int hf_png_chunk_flag_anc;
135
static int hf_png_chunk_flag_priv;
136
static int hf_png_chunk_flag_stc;
137
static int hf_png_chunk_len;
138
static int hf_png_chunk_type_str;
139
static int hf_png_gama_gamma;
140
static int hf_png_ihdr_bitdepth;
141
static int hf_png_ihdr_colour_type;
142
static int hf_png_ihdr_compression_method;
143
static int hf_png_ihdr_filter_method;
144
static int hf_png_ihdr_height;
145
static int hf_png_ihdr_interlace_method;
146
static int hf_png_ihdr_width;
147
static int hf_png_phys_horiz;
148
static int hf_png_phys_unit;
149
static int hf_png_phys_vert;
150
static int hf_png_signature;
151
static int hf_png_srgb_intent;
152
static int hf_png_text_keyword;
153
static int hf_png_text_string;
154
static int hf_png_time_day;
155
static int hf_png_time_hour;
156
static int hf_png_time_minute;
157
static int hf_png_time_month;
158
static int hf_png_time_second;
159
static int hf_png_time_year;
160
161
static int ett_png;
162
static int ett_png_chunk;
163
164
static expert_field ei_png_chunk_too_large;
165
166
static dissector_handle_t png_handle;
167
168
static void
169
dissect_png_ihdr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
170
0
{
171
0
    proto_tree_add_item(tree, hf_png_ihdr_width, tvb, 0, 4, ENC_BIG_ENDIAN);
172
0
    proto_tree_add_item(tree, hf_png_ihdr_height, tvb, 4, 4, ENC_BIG_ENDIAN);
173
0
    proto_tree_add_item(tree, hf_png_ihdr_bitdepth, tvb, 8, 1, ENC_BIG_ENDIAN);
174
0
    proto_tree_add_item(tree, hf_png_ihdr_colour_type, tvb, 9, 1, ENC_BIG_ENDIAN);
175
0
    proto_tree_add_item(tree, hf_png_ihdr_compression_method, tvb, 10, 1, ENC_BIG_ENDIAN);
176
0
    proto_tree_add_item(tree, hf_png_ihdr_filter_method, tvb, 11, 1, ENC_BIG_ENDIAN);
177
0
    proto_tree_add_item(tree, hf_png_ihdr_interlace_method, tvb, 12, 1, ENC_BIG_ENDIAN);
178
179
0
}
180
181
static void
182
dissect_png_srgb(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
183
0
{
184
0
    proto_tree_add_item(tree, hf_png_srgb_intent,
185
0
            tvb, 0, 1, ENC_BIG_ENDIAN);
186
0
}
187
188
static void
189
dissect_png_text(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
190
0
{
191
0
    unsigned offset=0, nul_offset;
192
0
    bool nul_offset_found;
193
194
0
    nul_offset_found = tvb_find_uint8_length(tvb, offset, tvb_captured_length_remaining(tvb, offset), 0, &nul_offset);
195
    /* nul_offset == 0 means empty keyword, this is not allowed by the png standard */
196
0
    if (nul_offset==0 || nul_offset_found == false) {
197
        /* XXX exception */
198
0
        return;
199
0
    }
200
201
0
    proto_tree_add_item(tree, hf_png_text_keyword, tvb, offset, nul_offset, ENC_ISO_8859_1);
202
0
    offset = nul_offset+1; /* length of the key word + 0 character */
203
204
0
    proto_tree_add_item(tree, hf_png_text_string, tvb, offset, tvb_captured_length_remaining(tvb, offset), ENC_ISO_8859_1);
205
206
0
}
207
208
static void
209
dissect_png_time(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
210
0
{
211
0
    proto_tree_add_item(tree, hf_png_time_year, tvb, 0, 2, ENC_BIG_ENDIAN);
212
0
    proto_tree_add_item(tree, hf_png_time_month, tvb, 2, 1, ENC_BIG_ENDIAN);
213
0
    proto_tree_add_item(tree, hf_png_time_day, tvb, 3, 1, ENC_BIG_ENDIAN);
214
0
    proto_tree_add_item(tree, hf_png_time_hour, tvb, 4, 1, ENC_BIG_ENDIAN);
215
0
    proto_tree_add_item(tree, hf_png_time_minute, tvb, 5, 1, ENC_BIG_ENDIAN);
216
0
    proto_tree_add_item(tree, hf_png_time_second, tvb, 6, 1, ENC_BIG_ENDIAN);
217
0
}
218
219
static void
220
dissect_png_phys(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
221
0
{
222
0
    proto_tree_add_item(tree, hf_png_phys_horiz, tvb, 0, 4, ENC_BIG_ENDIAN);
223
0
    proto_tree_add_item(tree, hf_png_phys_vert, tvb, 4, 4, ENC_BIG_ENDIAN);
224
0
    proto_tree_add_item(tree, hf_png_phys_unit, tvb, 8, 1, ENC_BIG_ENDIAN);
225
0
}
226
227
static void
228
dissect_png_bkgd(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
229
0
{
230
0
    switch(tvb_reported_length(tvb)){
231
0
        case 1: /* colour type 3 */
232
0
            proto_tree_add_item(tree, hf_png_bkgd_palette_index, tvb, 0, 1, ENC_BIG_ENDIAN);
233
0
            break;
234
0
        case 2: /* colour type 0, 4 */
235
0
            proto_tree_add_item(tree, hf_png_bkgd_greyscale, tvb, 0, 2, ENC_BIG_ENDIAN);
236
0
            break;
237
0
        case 6: /* colour type 2, 6 */
238
0
            proto_tree_add_item(tree, hf_png_bkgd_red, tvb, 0, 2, ENC_BIG_ENDIAN);
239
0
            proto_tree_add_item(tree, hf_png_bkgd_green, tvb, 2, 2, ENC_BIG_ENDIAN);
240
0
            proto_tree_add_item(tree, hf_png_bkgd_blue, tvb, 4, 2, ENC_BIG_ENDIAN);
241
0
            break;
242
0
    }
243
0
}
244
245
static void
246
dissect_png_chrm(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
247
0
{
248
0
    float  wx, wy, rx, ry, gx, gy, bx, by;
249
0
    unsigned offset = 0;
250
251
0
    wx = tvb_get_ntohl(tvb, offset) / 100000.0f;
252
0
    proto_tree_add_float(tree, hf_png_chrm_white_x,
253
0
            tvb, offset, 4, wx);
254
0
    offset += 4;
255
256
0
    wy = tvb_get_ntohl(tvb, offset) / 100000.0f;
257
0
    proto_tree_add_float(tree, hf_png_chrm_white_y,
258
0
            tvb, offset, 4, wy);
259
0
    offset += 4;
260
261
0
    rx = tvb_get_ntohl(tvb, offset) / 100000.0f;
262
0
    proto_tree_add_float(tree, hf_png_chrm_red_x,
263
0
            tvb, offset, 4, rx);
264
0
    offset += 4;
265
266
0
    ry = tvb_get_ntohl(tvb, offset) / 100000.0f;
267
0
    proto_tree_add_float(tree, hf_png_chrm_red_y,
268
0
            tvb, offset, 4, ry);
269
0
    offset += 4;
270
271
0
    gx = tvb_get_ntohl(tvb, offset) / 100000.0f;
272
0
    proto_tree_add_float(tree, hf_png_chrm_green_x,
273
0
            tvb, offset, 4, gx);
274
0
    offset += 4;
275
276
0
    gy = tvb_get_ntohl(tvb, offset) / 100000.0f;
277
0
    proto_tree_add_float(tree, hf_png_chrm_green_y,
278
0
            tvb, offset, 4, gy);
279
0
    offset += 4;
280
281
0
    bx = tvb_get_ntohl(tvb, offset) / 100000.0f;
282
0
    proto_tree_add_float(tree, hf_png_chrm_blue_x,
283
0
            tvb, offset, 4, bx);
284
0
    offset += 4;
285
286
0
    by = tvb_get_ntohl(tvb, offset) / 100000.0f;
287
0
    proto_tree_add_float(tree, hf_png_chrm_blue_y,
288
0
            tvb, offset, 4, by);
289
0
}
290
291
static void
292
dissect_png_gama(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
293
0
{
294
0
    float  gamma;
295
296
0
    gamma = tvb_get_ntohl(tvb, 0) / 100000.0f;
297
0
    proto_tree_add_float(tree, hf_png_gama_gamma,
298
0
            tvb, 0, 4, gamma);
299
0
}
300
301
static int
302
dissect_png(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void *data _U_)
303
187
{
304
187
    proto_tree *tree;
305
187
    proto_item *ti;
306
187
    unsigned    offset=0;
307
    /* http://libpng.org/pub/png/spec/1.2/PNG-Structure.html#PNG-file-signature */
308
187
    static const uint8_t magic[8] = { 137, 80, 78, 71, 13, 10, 26, 10 };
309
310
187
    if (tvb_captured_length(tvb) < 20)
311
36
        return 0;
312
151
    if (tvb_memeql(tvb, 0, magic, sizeof(magic)) != 0)
313
139
        return 0;
314
315
12
    col_append_str(pinfo->cinfo, COL_INFO, " (PNG)");
316
317
12
    ti=proto_tree_add_item(parent_tree, proto_png, tvb, offset, -1, ENC_NA);
318
12
    tree=proto_item_add_subtree(ti, ett_png);
319
320
12
    proto_tree_add_item(tree, hf_png_signature, tvb, offset, 8, ENC_NA);
321
12
    offset+=8;
322
323
159
    while(tvb_reported_length_remaining(tvb, offset) > 0){
324
148
        uint32_t    len_field;
325
148
        proto_item *len_it;
326
148
        proto_tree *chunk_tree;
327
148
        uint32_t    type;
328
148
        uint8_t    *type_str;
329
148
        tvbuff_t   *chunk_tvb;
330
331
148
        len_field = tvb_get_ntohl(tvb, offset);
332
333
148
        type = tvb_get_ntohl(tvb, offset+4);
334
148
        type_str = tvb_get_string_enc(pinfo->pool,
335
148
                tvb, offset+4, 4, ENC_ASCII|ENC_NA);
336
337
        /* 4 byte len field, 4 byte chunk type, 4 byte CRC */
338
148
        chunk_tree = proto_tree_add_subtree_format(tree, tvb, offset, 4+4+len_field+4, ett_png_chunk, NULL,
339
148
                "%s (%s)", val_to_str_const(type, chunk_types, "unknown"), type_str);
340
341
148
        len_it = proto_tree_add_item(chunk_tree, hf_png_chunk_len,
342
148
                tvb, offset, 4, ENC_BIG_ENDIAN);
343
148
        offset+=4;
344
148
        if (len_field > INT_MAX) {
345
1
            expert_add_info(pinfo, len_it, &ei_png_chunk_too_large);
346
1
            return offset;
347
1
        }
348
349
147
        proto_tree_add_item(chunk_tree, hf_png_chunk_type_str,
350
147
                tvb, offset, 4, ENC_ASCII);
351
352
147
        proto_tree_add_item(chunk_tree, hf_png_chunk_flag_anc, tvb, offset, 4, ENC_BIG_ENDIAN);
353
147
        proto_tree_add_item(chunk_tree, hf_png_chunk_flag_priv, tvb, offset, 4, ENC_BIG_ENDIAN);
354
147
        proto_tree_add_item(chunk_tree, hf_png_chunk_flag_stc, tvb, offset, 4, ENC_BIG_ENDIAN);
355
147
        offset+=4;
356
357
147
        chunk_tvb=tvb_new_subset_length(tvb, offset, len_field);
358
147
        switch (type) {
359
0
            case CHUNK_TYPE_IHDR:
360
0
                dissect_png_ihdr(chunk_tvb, pinfo, chunk_tree);
361
0
                break;
362
0
            case CHUNK_TYPE_bKGD:
363
0
                dissect_png_bkgd(chunk_tvb, pinfo, chunk_tree);
364
0
                break;
365
0
            case CHUNK_TYPE_cHRM:
366
0
                dissect_png_chrm(chunk_tvb, pinfo, chunk_tree);
367
0
                break;
368
0
            case CHUNK_TYPE_gAMA:
369
0
                dissect_png_gama(chunk_tvb, pinfo, chunk_tree);
370
0
                break;
371
0
            case CHUNK_TYPE_pHYs:
372
0
                dissect_png_phys(chunk_tvb, pinfo, chunk_tree);
373
0
                break;
374
0
            case CHUNK_TYPE_sRGB:
375
0
                dissect_png_srgb(chunk_tvb, pinfo, chunk_tree);
376
0
                break;
377
0
            case CHUNK_TYPE_tEXt:
378
0
                dissect_png_text(chunk_tvb, pinfo, chunk_tree);
379
0
                break;
380
0
            case CHUNK_TYPE_tIME:
381
0
                dissect_png_time(chunk_tvb, pinfo, chunk_tree);
382
0
                break;
383
147
            default:
384
147
                if (len_field>0) {
385
19
                    proto_tree_add_item(chunk_tree, hf_png_chunk_data,
386
19
                            tvb, offset, len_field, ENC_NA);
387
19
                }
388
147
                break;
389
147
        }
390
147
        offset += len_field;
391
392
147
        proto_tree_add_item(chunk_tree, hf_png_chunk_crc, tvb, offset, 4, ENC_BIG_ENDIAN);
393
147
        offset+=4;
394
147
    }
395
11
    return offset;
396
12
}
397
398
void
399
proto_register_png(void)
400
16
{
401
16
    static hf_register_info hf[] = {
402
16
        { &hf_png_signature,
403
16
            { "PNG Signature", "png.signature",
404
16
              FT_BYTES, BASE_NONE, NULL, 0,
405
16
              NULL, HFILL }
406
16
        },
407
16
        { &hf_png_chunk_data,
408
16
            { "Data", "png.chunk.data",
409
16
              FT_NONE, BASE_NONE, NULL, 0,
410
16
              NULL, HFILL }
411
16
        },
412
16
        { &hf_png_chunk_type_str,
413
16
            { "Type", "png.chunk.type",
414
16
              FT_STRING, BASE_NONE, NULL, 0,
415
16
              NULL, HFILL }
416
16
        },
417
16
        { &hf_png_chunk_len,
418
16
            { "Len", "png.chunk.len",
419
16
              FT_UINT32, BASE_DEC, NULL, 0,
420
16
              NULL, HFILL }
421
16
        },
422
16
        { &hf_png_chunk_crc,
423
16
            { "CRC", "png.chunk.crc",
424
16
              FT_UINT32, BASE_HEX, NULL, 0,
425
16
              NULL, HFILL }
426
16
        },
427
16
        { &hf_png_chunk_flag_anc,
428
16
            { "Ancillary", "png.chunk.flag.ancillary",
429
16
              FT_BOOLEAN, 32, TFS(&png_chunk_anc), 0x20000000,
430
16
              NULL, HFILL }
431
16
        },
432
16
        { &hf_png_chunk_flag_priv,
433
16
            { "Private", "png.chunk.flag.private",
434
16
              FT_BOOLEAN, 32, TFS(&png_chunk_priv), 0x00200000,
435
16
              NULL, HFILL }
436
16
        },
437
16
        { &hf_png_chunk_flag_stc,
438
16
            { "Safe To Copy", "png.chunk.flag.stc",
439
16
              FT_BOOLEAN, 32, TFS(&png_chunk_stc), 0x00000020,
440
16
              NULL, HFILL }
441
16
        },
442
16
        { &hf_png_ihdr_width,
443
16
            { "Width", "png.ihdr.width",
444
16
              FT_UINT32, BASE_DEC, NULL, 0,
445
16
              NULL, HFILL }
446
16
        },
447
16
        { &hf_png_ihdr_height,
448
16
            { "Height", "png.ihdr.height",
449
16
              FT_UINT32, BASE_DEC, NULL, 0,
450
16
              NULL, HFILL }
451
16
        },
452
16
        { &hf_png_ihdr_bitdepth,
453
16
            { "Bit Depth", "png.ihdr.bitdepth",
454
16
              FT_UINT8, BASE_DEC, NULL, 0,
455
16
              NULL, HFILL }
456
16
        },
457
16
        { &hf_png_ihdr_colour_type,
458
16
            { "Colour Type", "png.ihdr.colour_type",
459
16
              FT_UINT8, BASE_DEC, VALS(colour_type_vals), 0,
460
16
              NULL, HFILL }
461
16
        },
462
16
        { &hf_png_ihdr_compression_method,
463
16
            { "Compression Method", "png.ihdr.compression_method",
464
16
              FT_UINT8, BASE_DEC, VALS(compression_method_vals), 0,
465
16
              NULL, HFILL }
466
16
        },
467
16
        { &hf_png_ihdr_filter_method,
468
16
            { "Filter Method", "png.ihdr.filter_method",
469
16
              FT_UINT8, BASE_DEC, VALS(filter_method_vals), 0,
470
16
              NULL, HFILL }
471
16
        },
472
16
        { &hf_png_ihdr_interlace_method,
473
16
            { "Interlace Method", "png.ihdr.interlace_method",
474
16
              FT_UINT8, BASE_DEC, VALS(interlace_method_vals), 0,
475
16
              NULL, HFILL }
476
16
        },
477
16
        { &hf_png_srgb_intent,
478
16
            { "Intent", "png.srgb.intent",
479
16
              FT_UINT8, BASE_DEC, VALS(srgb_intent_vals), 0,
480
16
              NULL, HFILL }
481
16
        },
482
16
        { &hf_png_text_keyword,
483
16
            { "Keyword", "png.text.keyword",
484
16
              FT_STRING, BASE_NONE, NULL, 0,
485
16
              NULL, HFILL }
486
16
        },
487
16
        { &hf_png_text_string,
488
16
            { "String", "png.text.string",
489
16
              FT_STRING, BASE_NONE, NULL, 0,
490
16
              NULL, HFILL }
491
16
        },
492
16
        { &hf_png_time_year,
493
16
            { "Year", "png.time.year",
494
16
              FT_UINT16, BASE_DEC, NULL, 0,
495
16
              NULL, HFILL }
496
16
        },
497
16
        { &hf_png_time_month,
498
16
            { "Month", "png.time.month",
499
16
              FT_UINT8, BASE_DEC, NULL, 0,
500
16
              NULL, HFILL }
501
16
        },
502
16
        { &hf_png_time_day,
503
16
            { "Day", "png.time.day",
504
16
              FT_UINT8, BASE_DEC, NULL, 0,
505
16
              NULL, HFILL }
506
16
        },
507
16
        { &hf_png_time_hour,
508
16
            { "Hour", "png.time.hour",
509
16
              FT_UINT8, BASE_DEC, NULL, 0,
510
16
              NULL, HFILL }
511
16
        },
512
16
        { &hf_png_time_minute,
513
16
            { "Minute", "png.time.minute",
514
16
              FT_UINT8, BASE_DEC, NULL, 0,
515
16
              NULL, HFILL }
516
16
        },
517
16
        { &hf_png_time_second,
518
16
            { "Second", "png.time.second",
519
16
              FT_UINT8, BASE_DEC, NULL, 0,
520
16
              NULL, HFILL }
521
16
        },
522
16
        { &hf_png_phys_horiz,
523
16
            { "Horizontal pixels per unit", "png.phys.horiz",
524
16
              FT_UINT32, BASE_DEC, NULL, 0,
525
16
              NULL, HFILL }
526
16
        },
527
16
        { &hf_png_phys_vert,
528
16
            { "Vertical pixels per unit", "png.phys.vert",
529
16
              FT_UINT32, BASE_DEC, NULL, 0,
530
16
              NULL, HFILL }
531
16
        },
532
16
        { &hf_png_phys_unit,
533
16
            { "Unit", "png.phys.unit",
534
16
              FT_UINT8, BASE_DEC, VALS(phys_unit_vals), 0,
535
16
              NULL, HFILL }
536
16
        },
537
16
        { &hf_png_bkgd_palette_index,
538
16
            { "Palette Index", "png.bkgd.palette_index",
539
16
              FT_UINT8, BASE_DEC, NULL, 0,
540
16
              NULL, HFILL }
541
16
        },
542
16
        { &hf_png_bkgd_greyscale,
543
16
            { "Greyscale", "png.bkgd.greyscale",
544
16
              FT_UINT16, BASE_HEX, NULL, 0,
545
16
              NULL, HFILL }
546
16
        },
547
16
        { &hf_png_bkgd_red,
548
16
            { "Red", "png.bkgd.red",
549
16
              FT_UINT16, BASE_HEX, NULL, 0,
550
16
              NULL, HFILL }
551
16
        },
552
16
        { &hf_png_bkgd_green,
553
16
            { "Green", "png.bkgd.green",
554
16
              FT_UINT16, BASE_HEX, NULL, 0,
555
16
              NULL, HFILL }
556
16
        },
557
16
        { &hf_png_bkgd_blue,
558
16
            { "Blue", "png.bkgd.blue",
559
16
              FT_UINT16, BASE_HEX, NULL, 0,
560
16
              NULL, HFILL }
561
16
        },
562
16
        { &hf_png_chrm_white_x,
563
16
            { "White X", "png.chrm.white.x",
564
16
              FT_FLOAT, BASE_NONE, NULL, 0,
565
16
              NULL, HFILL }
566
16
        },
567
16
        { &hf_png_chrm_white_y,
568
16
            { "White Y", "png.chrm.white.y",
569
16
              FT_FLOAT, BASE_NONE, NULL, 0,
570
16
              NULL, HFILL }
571
16
        },
572
16
        { &hf_png_chrm_red_x,
573
16
            { "Red X", "png.chrm.red.x",
574
16
              FT_FLOAT, BASE_NONE, NULL, 0,
575
16
              NULL, HFILL }
576
16
        },
577
16
        { &hf_png_chrm_red_y,
578
16
            { "Red Y", "png.chrm.red.y",
579
16
              FT_FLOAT, BASE_NONE, NULL, 0,
580
16
              NULL, HFILL }
581
16
        },
582
16
        { &hf_png_chrm_green_x,
583
16
            { "Green X", "png.chrm.green.x",
584
16
              FT_FLOAT, BASE_NONE, NULL, 0,
585
16
              NULL, HFILL }
586
16
        },
587
16
        { &hf_png_chrm_green_y,
588
16
            { "Green Y", "png.chrm.green.y",
589
16
              FT_FLOAT, BASE_NONE, NULL, 0,
590
16
              NULL, HFILL }
591
16
        },
592
16
        { &hf_png_chrm_blue_x,
593
16
            { "Blue X", "png.chrm.blue.x",
594
16
              FT_FLOAT, BASE_NONE, NULL, 0,
595
16
              NULL, HFILL }
596
16
        },
597
16
        { &hf_png_chrm_blue_y,
598
16
            { "Blue Y", "png.chrm.blue.y",
599
16
              FT_FLOAT, BASE_NONE, NULL, 0,
600
16
              NULL, HFILL }
601
16
        },
602
16
        { &hf_png_gama_gamma,
603
16
            { "Gamma", "png.gama.gamma",
604
16
              FT_FLOAT, BASE_NONE, NULL, 0,
605
16
              NULL, HFILL }
606
16
        },
607
16
    };
608
609
16
    static int *ett[] =
610
16
    {
611
16
        &ett_png,
612
16
        &ett_png_chunk,
613
16
    };
614
615
16
    static ei_register_info ei[] = {
616
16
        { &ei_png_chunk_too_large,
617
16
            { "png.chunk_too_large", PI_PROTOCOL, PI_WARN,
618
16
                "chunk size too large, dissection of this chunk is not supported", EXPFILL }}
619
16
    };
620
16
    expert_module_t *expert_png;
621
622
16
    proto_png = proto_register_protocol("Portable Network Graphics","PNG","png");
623
16
    proto_register_field_array(proto_png, hf, array_length(hf));
624
16
    proto_register_subtree_array(ett, array_length(ett));
625
626
16
    expert_png = expert_register_protocol(proto_png);
627
16
    expert_register_field_array(expert_png, ei, array_length(ei));
628
629
16
    png_handle = register_dissector("png", dissect_png, proto_png);
630
16
}
631
632
static bool dissect_png_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
633
187
{
634
187
    return dissect_png(tvb, pinfo, tree, data) > 0;
635
187
}
636
637
void
638
proto_reg_handoff_png(void)
639
16
{
640
16
    dissector_add_string("media_type", "image/png", png_handle);
641
16
    heur_dissector_add("http", dissect_png_heur, "PNG file in HTTP", "png_http", proto_png, HEURISTIC_ENABLE);
642
16
    heur_dissector_add("wtap_file", dissect_png_heur, "PNG file in HTTP", "png_wtap", proto_png, HEURISTIC_ENABLE);
643
16
}
644
645
/*
646
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
647
 *
648
 * Local variables:
649
 * c-basic-offset: 4
650
 * tab-width: 8
651
 * indent-tabs-mode: nil
652
 * End:
653
 *
654
 * vi: set shiftwidth=4 tabstop=8 expandtab:
655
 * :indentSize=4:tabSize=8:noTabs=true:
656
 */