exiftool-vendored.exe 12.69.0 → 12.70.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/bin/exiftool_files/Changes +43 -12
  2. package/bin/exiftool_files/README +2 -2
  3. package/bin/exiftool_files/exiftool.pl +13 -13
  4. package/bin/exiftool_files/lib/Image/ExifTool/CBOR.pm +18 -2
  5. package/bin/exiftool_files/lib/Image/ExifTool/Canon.pm +63 -16
  6. package/bin/exiftool_files/lib/Image/ExifTool/DJI.pm +3 -2
  7. package/bin/exiftool_files/lib/Image/ExifTool/EXE.pm +54 -6
  8. package/bin/exiftool_files/lib/Image/ExifTool/Exif.pm +82 -3
  9. package/bin/exiftool_files/lib/Image/ExifTool/FujiFilm.pm +142 -20
  10. package/bin/exiftool_files/lib/Image/ExifTool/GIF.pm +5 -1
  11. package/bin/exiftool_files/lib/Image/ExifTool/ID3.pm +70 -7
  12. package/bin/exiftool_files/lib/Image/ExifTool/InDesign.pm +1 -1
  13. package/bin/exiftool_files/lib/Image/ExifTool/JPEG.pm +1 -1
  14. package/bin/exiftool_files/lib/Image/ExifTool/Jpeg2000.pm +30 -15
  15. package/bin/exiftool_files/lib/Image/ExifTool/MakerNotes.pm +2 -2
  16. package/bin/exiftool_files/lib/Image/ExifTool/Nikon.pm +45 -12
  17. package/bin/exiftool_files/lib/Image/ExifTool/Olympus.pm +7 -1
  18. package/bin/exiftool_files/lib/Image/ExifTool/PNG.pm +8 -13
  19. package/bin/exiftool_files/lib/Image/ExifTool/Panasonic.pm +10 -1
  20. package/bin/exiftool_files/lib/Image/ExifTool/QuickTime.pm +31 -4
  21. package/bin/exiftool_files/lib/Image/ExifTool/README +7 -2
  22. package/bin/exiftool_files/lib/Image/ExifTool/RIFF.pm +53 -9
  23. package/bin/exiftool_files/lib/Image/ExifTool/Sony.pm +95 -34
  24. package/bin/exiftool_files/lib/Image/ExifTool/TagLookup.pm +6927 -6856
  25. package/bin/exiftool_files/lib/Image/ExifTool/TagNames.pod +435 -304
  26. package/bin/exiftool_files/lib/Image/ExifTool/Text.pm +4 -5
  27. package/bin/exiftool_files/lib/Image/ExifTool/Validate.pm +6 -5
  28. package/bin/exiftool_files/lib/Image/ExifTool/WriteQuickTime.pl +1 -0
  29. package/bin/exiftool_files/lib/Image/ExifTool/WriteRIFF.pl +9 -3
  30. package/bin/exiftool_files/lib/Image/ExifTool/Writer.pl +21 -36
  31. package/bin/exiftool_files/lib/Image/ExifTool.pm +59 -33
  32. package/bin/exiftool_files/lib/Image/ExifTool.pod +9 -3
  33. package/package.json +3 -3
@@ -962,8 +962,8 @@ my %imageAreaZ9b = (
962
962
  );
963
963
 
964
964
  my %infoZSeries = (
965
- Condition => '$$self{Model} =~ /^NIKON Z (30|5|50|6|6_2|7|7_2|8|fc|9)\b/i',
966
- Notes => 'Z Series cameras thru July 2023',
965
+ Condition => '$$self{Model} =~ /^NIKON Z (30|5|50|6|6_2|7|7_2|8|f|fc|9)\b/i',
966
+ Notes => 'Z Series cameras thru October 2023',
967
967
  );
968
968
 
969
969
  my %iSOAutoHiLimitZ7 = (
@@ -2582,9 +2582,21 @@ my %base64coord = (
2582
2582
  DirOffset => 4,
2583
2583
  },
2584
2584
  },
2585
- { # (D5200/D7100=0218, D5300=0219, D610/Df=0220, D3300=0221, CoolpixA=0601)
2586
- Name => 'ColorBalanceUnknown02',
2587
- Condition => '$$valPt =~ /^0[26]/',
2585
+ { #PH (NC)
2586
+ # (D5300=0219, D3300=0221, D4S=0222, D750/D810=0223, D3400/D3500/D5500/D5600/D7200=0224)
2587
+ Condition => '$$valPt =~ /^02(19|2[1234])/',
2588
+ Name => 'ColorBalance0219',
2589
+ SubDirectory => {
2590
+ TagTable => 'Image::ExifTool::Nikon::ColorBalance2',
2591
+ ProcessProc => \&ProcessNikonEncrypted,
2592
+ WriteProc => \&ProcessNikonEncrypted,
2593
+ DecryptStart => 4,
2594
+ DirOffset => 0x7c,
2595
+ },
2596
+ },
2597
+ { # (D610/Df=0220, CoolpixA=0601)
2598
+ Name => 'ColorBalanceUnknown1',
2599
+ Condition => '$$valPt =~ /^0(220|6)/',
2588
2600
  SubDirectory => {
2589
2601
  TagTable => 'Image::ExifTool::Nikon::ColorBalanceUnknown',
2590
2602
  ProcessProc => \&ProcessNikonEncrypted,
@@ -2592,11 +2604,12 @@ my %base64coord = (
2592
2604
  DecryptStart => 284,
2593
2605
  },
2594
2606
  },
2595
- { # (1J1/1J2/1V1=0400, 1V2=0401, 1J3/1S1=0402, 1AW1=0403, Z6/Z7=0800)
2596
- Name => 'ColorBalanceUnknown04',
2597
- Condition => '$$valPt =~ /^0[48]/',
2607
+ { # (D5200/D7200=0218, D5/D500=0225, D7500=0226, D850=0227, D6/D780=0228,
2608
+ # 1J1/1J2/1V1=0400, 1V2=0401, 1J3/1S1=0402, 1AW1=0403, Z6/Z7=0800)
2609
+ Name => 'ColorBalanceUnknown2',
2610
+ Condition => '$$valPt =~ /^0(18|[248])/',
2598
2611
  SubDirectory => {
2599
- TagTable => 'Image::ExifTool::Nikon::ColorBalanceUnknown',
2612
+ TagTable => 'Image::ExifTool::Nikon::ColorBalanceUnknown2',
2600
2613
  ProcessProc => \&ProcessNikonEncrypted,
2601
2614
  WriteProc => \&ProcessNikonEncrypted, # (necessary to recrypt this if serial number changed)
2602
2615
  DecryptStart => 4,
@@ -4956,6 +4969,16 @@ my %nrwLevels = (
4956
4969
  },
4957
4970
  );
4958
4971
 
4972
+ %Image::ExifTool::Nikon::ColorBalanceUnknown2 = (
4973
+ %binaryDataAttrs,
4974
+ GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
4975
+ FORMAT => 'int16u',
4976
+ 0 => {
4977
+ Name => 'ColorBalanceVersion',
4978
+ Format => 'undef[4]',
4979
+ },
4980
+ );
4981
+
4959
4982
  %Image::ExifTool::Nikon::Type2 = (
4960
4983
  WRITE_PROC => \&Image::ExifTool::Exif::WriteExif,
4961
4984
  CHECK_PROC => \&Image::ExifTool::Exif::CheckExif,
@@ -5448,7 +5471,7 @@ my %nikonFocalConversions = (
5448
5471
  43 => 'NIKKOR Z DX 24mm f/1.7', #28
5449
5472
  44 => 'NIKKOR Z 70-180mm f/2.8', #28
5450
5473
  45 => 'NIKKOR Z 600mm f/6.3 VR S', #28
5451
- 48 => 'Nikkor Z 135mm f/1.8 S Plena', #28
5474
+ 46 => 'Nikkor Z 135mm f/1.8 S Plena', #28
5452
5475
  32768 => 'Nikkor Z 400mm f/2.8 TC VR S TC-1.4x', #28
5453
5476
  32769 => 'Nikkor Z 600mm f/4 TC VR S TC-1.4x', #28
5454
5477
  },
@@ -8195,7 +8218,7 @@ my %nikonFocalConversions = (
8195
8218
  CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
8196
8219
  VARS => { ID_LABEL => 'Index', NIKON_OFFSETS => 0x24 },
8197
8220
  DATAMEMBER => [ 0x04 ],
8198
- IS_SUBDIR => [ 0x30, 0x38, 0x98, 0xa0 ],
8221
+ IS_SUBDIR => [ 0x30, 0x38, 0x88, 0x98, 0xa0 ],
8199
8222
  WRITABLE => 1,
8200
8223
  GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
8201
8224
  NOTES => 'These tags are extracted from encrypted data in images from the Z7II.',
@@ -8245,9 +8268,19 @@ my %nikonFocalConversions = (
8245
8268
  Start => '$val',
8246
8269
  }
8247
8270
  },
8271
+ 0x88 => {
8272
+ Name => 'OrientationOffset',
8273
+ Format => 'int32u',
8274
+ Condition => '$$self{Model} =~ /^NIKON Z f\b/i',
8275
+ SubDirectory => {
8276
+ TagTable => 'Image::ExifTool::Nikon::OrientationInfo',
8277
+ Start => '$val',
8278
+ }
8279
+ },
8248
8280
  0x98 => {
8249
8281
  Name => 'OrientationOffset',
8250
8282
  Format => 'int32u',
8283
+ Condition => '$$self{Model} =~ /^NIKON Z (30|5|50|6|6_2|7|7_2|8|fc)\b/i', #models other then the Z f
8251
8284
  SubDirectory => {
8252
8285
  TagTable => 'Image::ExifTool::Nikon::OrientationInfo',
8253
8286
  Start => '$val',
@@ -8514,7 +8547,7 @@ my %nikonFocalConversions = (
8514
8547
  0x002a => {
8515
8548
  Name => 'IntervalFrame',
8516
8549
  RawConv => '$$self{IntervalFrame} = $val',
8517
- Condition => '$$self{ShutterMode} and $$self{ShutterMode} ne 96 and $$self{FocusShiftShooting} > 0', #not valid for C30/C60/C120
8550
+ Condition => '$$self{ShutterMode} and $$self{ShutterMode} ne 96 and $$self{IntervalShooting} > 0', #not valid for C30/C60/C120
8518
8551
  Format => 'int16u',
8519
8552
  Hidden => 1,
8520
8553
  },
@@ -40,7 +40,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
40
40
  use Image::ExifTool::Exif;
41
41
  use Image::ExifTool::APP12;
42
42
 
43
- $VERSION = '2.81';
43
+ $VERSION = '2.82';
44
44
 
45
45
  sub PrintLensInfo($$$);
46
46
 
@@ -186,7 +186,9 @@ my %olympusLensTypes = (
186
186
  '2 36 10' => 'Leica DG Elmarit 200mm F2.8 Power OIS', #IB
187
187
  '2 37 10' => 'Leica DG Vario-Elmarit 50-200mm F2.8-4 Asph. Power OIS', #IB
188
188
  '2 38 10' => 'Leica DG Vario-Summilux 10-25mm F1.7 Asph.', #IB
189
+ '2 39 10' => 'Leica DG Summilux 25mm F1.4 II Asph.', #forum15345
189
190
  '2 40 10' => 'Leica DG Vario-Summilux 25-50mm F1.7 Asph.', #IB (H-X2550)
191
+ '2 41 10' => 'Leica DG Summilux 9mm F1.7 Asph.', #forum15345
190
192
  '3 01 00' => 'Leica D Vario Elmarit 14-50mm F2.8-3.5 Asph.', #11
191
193
  '3 02 00' => 'Leica D Summilux 25mm F1.4 Asph.', #11
192
194
  # Tamron lenses
@@ -358,6 +360,7 @@ my %olympusCameraTypes = (
358
360
  D4521 => 'SH-25MR',
359
361
  D4523 => 'SP-720UZ',
360
362
  D4529 => 'VG170',
363
+ D4530 => 'VH210',
361
364
  D4531 => 'XZ-2',
362
365
  D4535 => 'SP-620UZ',
363
366
  D4536 => 'TG-320',
@@ -383,9 +386,11 @@ my %olympusCameraTypes = (
383
386
  D4585 => 'SH-2 / SH-3',
384
387
  D4586 => 'TG-4',
385
388
  D4587 => 'TG-860',
389
+ D4590 => 'TG-TRACKER',
386
390
  D4591 => 'TG-870',
387
391
  D4593 => 'TG-5', #IB
388
392
  D4603 => 'TG-6', #IB
393
+ D4605 => 'TG-7',
389
394
  D4809 => 'C2500L',
390
395
  D4842 => 'E-10',
391
396
  D4856 => 'C-1',
@@ -431,6 +436,7 @@ my %olympusCameraTypes = (
431
436
  S0076 => 'E-PL9', #IB
432
437
  S0080 => 'E-M1X', #IB
433
438
  S0085 => 'E-PL10', #IB
439
+ S0088 => 'E-M10MarkIV',
434
440
  S0089 => 'E-M5MarkIII',
435
441
  S0092 => 'E-M1MarkIII', #IB
436
442
  S0093 => 'E-P7', #IB
@@ -80,6 +80,7 @@ my %pngMap = (
80
80
  ICC_Profile => 'PNG',
81
81
  Photoshop => 'PNG',
82
82
  'PNG-pHYs' => 'PNG',
83
+ JUMBF => 'PNG',
83
84
  IPTC => 'Photoshop',
84
85
  MakerNotes => 'ExifIFD',
85
86
  );
@@ -341,6 +342,7 @@ my %noLeapFrog = ( SAVE => 1, SEEK => 1, IHDR => 1, JHDR => 1, IEND => 1, MEND =
341
342
  },
342
343
  caBX => { # C2PA metadata
343
344
  Name => 'JUMBF',
345
+ Deletable => 1,
344
346
  SubDirectory => { TagTable => 'Image::ExifTool::Jpeg2000::Main' },
345
347
  },
346
348
  cICP => {
@@ -973,20 +975,13 @@ sub FoundPNG($$$$;$$$$)
973
975
  undef $processProc if $wasCompressed and $processProc and $processProc eq \&ProcessPNG_Compressed;
974
976
  # rewrite this directory if necessary (but always process TextualData normally)
975
977
  if ($outBuff and not $processProc and $subTable ne \%Image::ExifTool::PNG::TextualData) {
976
- # allow JUMBF to be deleted (may want to expand this for other types too?)
977
- if ($dirName eq 'JUMBF' and $$et{DEL_GROUP}{$dirName}) {
978
- $$outBuff = '';
979
- ++$$et{CHANGED};
980
- $et->VPrint(0, " Deleting $dirName");
981
- } else {
982
- return 1 unless $$et{EDIT_DIRS}{$dirName};
983
- $$outBuff = $et->WriteDirectory(\%subdirInfo, $subTable);
984
- if ($tagName eq 'XMP' and $$outBuff) {
985
- # make sure the XMP is marked as read-only
986
- Image::ExifTool::XMP::ValidateXMP($outBuff,'r');
987
- }
988
- DoneDir($et, $dirName, $outBuff, $$tagInfo{NonStandard});
978
+ return 1 unless $$et{EDIT_DIRS}{$dirName};
979
+ $$outBuff = $et->WriteDirectory(\%subdirInfo, $subTable);
980
+ if ($tagName eq 'XMP' and $$outBuff) {
981
+ # make sure the XMP is marked as read-only
982
+ Image::ExifTool::XMP::ValidateXMP($outBuff,'r');
989
983
  }
984
+ DoneDir($et, $dirName, $outBuff, $$tagInfo{NonStandard});
990
985
  } else {
991
986
  $processed = $et->ProcessDirectory(\%subdirInfo, $subTable, $processProc);
992
987
  }
@@ -37,7 +37,7 @@ use vars qw($VERSION %leicaLensTypes);
37
37
  use Image::ExifTool qw(:DataAccess :Utils);
38
38
  use Image::ExifTool::Exif;
39
39
 
40
- $VERSION = '2.20';
40
+ $VERSION = '2.21';
41
41
 
42
42
  sub ProcessLeicaLEIC($$$);
43
43
  sub WhiteBalanceConv($;$$);
@@ -1991,6 +1991,15 @@ my %shootingMode = (
1991
1991
  },
1992
1992
  PrintConvInv => '$_=$val; tr/A-Z0-9//dc; s/(.{3})(19|20)/$1/; $_',
1993
1993
  },
1994
+ 0x05ff => {
1995
+ Name => 'CameraIFD', # (Leica Q3)
1996
+ Condition => '$$valPt =~ /^(II\x2a\0\x08\0\0\0|MM\0\x2a\0\0\0\x08)/',
1997
+ SubDirectory => {
1998
+ TagTable => 'Image::ExifTool::PanasonicRaw::CameraIFD',
1999
+ Base => '$start',
2000
+ ProcessProc => \&Image::ExifTool::ProcessTIFF,
2001
+ },
2002
+ },
1994
2003
  );
1995
2004
 
1996
2005
  # Leica type5 ShotInfo (ref PH) (X2)
@@ -48,7 +48,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
48
48
  use Image::ExifTool::Exif;
49
49
  use Image::ExifTool::GPS;
50
50
 
51
- $VERSION = '2.88';
51
+ $VERSION = '2.89';
52
52
 
53
53
  sub ProcessMOV($$;$);
54
54
  sub ProcessKeys($$$);
@@ -638,6 +638,33 @@ my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 );
638
638
  Condition => '$$valPt=~/^\xef\xe1\x58\x9a\xbb\x77\x49\xef\x80\x95\x27\x75\x9e\xb1\xdc\x6f/ and $$self{OPTIONS}{ExtractEmbedded}',
639
639
  SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Tags360Fly' },
640
640
  },
641
+ { #https://c2pa.org/specifications/
642
+ Name => 'JUMBF',
643
+ Condition => '$$valPt=~/^\xd8\xfe\xc3\xd6\x1b\x0e\x48\x3c\x92\x97\x58\x28\x87\x7e\xc4\x81.{4}manifest\0/s',
644
+ Deletable => 1,
645
+ SubDirectory => {
646
+ TagTable => 'Image::ExifTool::Jpeg2000::Main',
647
+ # 16 bytes uuid
648
+ # +4 bytes 0
649
+ # +9 bytes "manifest\0"
650
+ # +8 bytes absolute(!!!) offset to C2PA uuid "merkle\0" box
651
+ # =37 bytes total
652
+ Start => 37,
653
+ },
654
+ },
655
+ { #https://c2pa.org/specifications/ (NC)
656
+ Name => 'CBOR',
657
+ Condition => '$$valPt=~/^\xd8\xfe\xc3\xd6\x1b\x0e\x48\x3c\x92\x97\x58\x28\x87\x7e\xc4\x81.{4}merkle\0/s',
658
+ Deletable => 1, # (NC)
659
+ SubDirectory => {
660
+ TagTable => 'Image::ExifTool::CBOR::Main',
661
+ # 16 bytes uuid
662
+ # +4 bytes 0
663
+ # +7 bytes "merkle\0"
664
+ # =27 bytes total
665
+ Start => 27,
666
+ },
667
+ },
641
668
  {
642
669
  Name => 'SensorData',
643
670
  Condition => '$$valPt=~/^\xef\xe1\x58\x9a\xbb\x77\x49\xef\x80\x95\x27\x75\x9e\xb1\xdc\x6f/',
@@ -9504,7 +9531,7 @@ sub ProcessMOV($$;$)
9504
9531
  # stop processing at mdat/idat if -fast2 is used
9505
9532
  last if $fast > 1 and ($tag eq 'mdat' or ($tag eq 'idat' and $$et{FileType} ne 'HEIC'));
9506
9533
  # load values only if associated with a tag (or verbose) and not too big
9507
- if ($size > 0x2000000) { # start to get worried above 32 MB
9534
+ if ($size > 0x2000000) { # start to get worried above 32 MiB
9508
9535
  # check for RIFF trailer (written by Auto-Vox dashcam)
9509
9536
  if ($buff =~ /^(gpsa|gps0|gsen|gsea)...\0/s) { # (yet seen only gpsa as first record)
9510
9537
  $et->VPrint(0, "Found RIFF trailer");
@@ -9521,9 +9548,9 @@ sub ProcessMOV($$;$)
9521
9548
  if ($tagInfo and not $$tagInfo{Unknown} and not $eeTag) {
9522
9549
  my $t = PrintableTagID($tag,2);
9523
9550
  if ($size > 0x8000000) {
9524
- $et->Warn("Skipping '${t}' atom > 128 MB", 1);
9551
+ $et->Warn("Skipping '${t}' atom > 128 MiB", 1);
9525
9552
  } else {
9526
- $et->Warn("Skipping '${t}' atom > 32 MB", 2) or $ignore = 0;
9553
+ $et->Warn("Skipping '${t}' atom > 32 MiB", 2) or $ignore = 0;
9527
9554
  }
9528
9555
  }
9529
9556
  }
@@ -616,9 +616,9 @@ numerical, and generated automatically otherwise.
616
616
  arguments: the value, a flag which is set for the inverse
617
617
  conversion, and a reference to the PrintConv hash, and returns
618
618
  the converted value or undef on error -- it may call warn() to
619
- return an error message. The lookup hash may also contain a
619
+ return an error message. The lookup hash may also contain a
620
620
  'Notes' entry which is used for documentation if the
621
- SeparateTable flag is set). In an expression, $self is a
621
+ SeparateTable flag is set). In an expression, $self is a
622
622
  reference to the current ExifTool object, $val is the Raw
623
623
  value, and $tag is the tag key. The subroutine takes 2
624
624
  arguments: the Raw value and a reference to the current
@@ -894,6 +894,11 @@ numerical, and generated automatically otherwise.
894
894
  writing this tag. Only needed if tag can be written to
895
895
  groups other than the normal groups for this tag (very rare).
896
896
 
897
+ Deletable : [Writable SubDirectory's only] Overrides internal test for
898
+ metadata types with permanent directories (currently QuickTime
899
+ and Jpeg2000), allowing the tag containing these directories
900
+ to be deleted
901
+
897
902
  OffsetPair : Used in EXIF table to specify the tagID for the corresponding
898
903
  offset or length tag.
899
904
 
@@ -30,7 +30,7 @@ use strict;
30
30
  use vars qw($VERSION $AUTOLOAD);
31
31
  use Image::ExifTool qw(:DataAccess :Utils);
32
32
 
33
- $VERSION = '1.66';
33
+ $VERSION = '1.67';
34
34
 
35
35
  sub ConvertTimecode($);
36
36
  sub ProcessSGLT($$$);
@@ -500,6 +500,11 @@ my %code2charset = (
500
500
  Name => 'OldXMP',
501
501
  Binary => 1,
502
502
  },
503
+ C2PA => { #https://c2pa.org/specifications/
504
+ Name => 'JUMBF',
505
+ Deletable => 1,
506
+ SubDirectory => { TagTable => 'Image::ExifTool::Jpeg2000::Main' },
507
+ },
503
508
  olym => {
504
509
  Name => 'Olym',
505
510
  SubDirectory => { TagTable => 'Image::ExifTool::Olympus::WAV' },
@@ -1069,7 +1074,16 @@ my %code2charset = (
1069
1074
  },
1070
1075
  1 => {
1071
1076
  Name => 'MaxDataRate',
1072
- PrintConv => 'sprintf("%.4g kB/s",$val / 1024)',
1077
+ Notes => q{
1078
+ converted using SI byte prefixes unles the API ByteUnit option is set to
1079
+ "Binary"
1080
+ },
1081
+ PrintConv => q{
1082
+ my ($unit, $div) = $self->Options('ByteUnit') eq 'Binary' ? ('KiB/s',1024) : ('kB/s',1000);
1083
+ my $tmp = $val / $div;
1084
+ $tmp > 9999 and $tmp /= $div, $unit =~ s/^./M/;
1085
+ sprintf('%.4g %s', $tmp, $unit);
1086
+ },
1073
1087
  },
1074
1088
  # 2 => 'PaddingGranularity',
1075
1089
  # 3 => 'Flags',
@@ -1989,7 +2003,7 @@ sub ProcessRIFF($$)
1989
2003
  {
1990
2004
  my ($et, $dirInfo) = @_;
1991
2005
  my $raf = $$dirInfo{RAF};
1992
- my ($buff, $buf2, $type, $mime, $err, $rf64);
2006
+ my ($buff, $buf2, $type, $mime, $err, $rf64, $moviEnd);
1993
2007
  my $verbose = $et->Options('Verbose');
1994
2008
  my $unknown = $et->Options('Unknown');
1995
2009
  my $validate = $et->Options('Validate');
@@ -2023,8 +2037,34 @@ sub ProcessRIFF($$)
2023
2037
  # Read chunks in RIFF image
2024
2038
  #
2025
2039
  for (;;) {
2040
+ if ($err) {
2041
+ last unless $moviEnd;
2042
+ # we arrived here because there was a problem parsing the movie data
2043
+ # so seek to the end to continue processing
2044
+ if ($moviEnd > 0x7fffffff and not $et->Options('LargeFileSupport')) {
2045
+ $et->Warn('Possibly corrupt LIST_movi data');
2046
+ $et->Warn('Stopped parsing at large LIST_movi chunk (LargeFileSupport not set)');
2047
+ undef $err;
2048
+ last;
2049
+ }
2050
+ if ($validate) {
2051
+ # (must actually try to read something after seeking to detect error)
2052
+ $raf->Seek($moviEnd-1, 0) and $raf->Read($buff, 1) == 1 or last;
2053
+ } else {
2054
+ $raf->Seek($moviEnd, 0) or last;
2055
+ }
2056
+ $pos = $moviEnd;
2057
+ $et->Warn('Possibly corrupt LIST_movi data');
2058
+ undef $err;
2059
+ undef $moviEnd;
2060
+ }
2061
+ if ($moviEnd) {
2062
+ $pos > $moviEnd and $err = 1, next; # error if we parsed past the end of the movie data
2063
+ undef $moviEnd if $pos == $moviEnd; # parsed all movie data?
2064
+ }
2026
2065
  my $num = $raf->Read($buff, 8);
2027
2066
  if ($num < 8) {
2067
+ $moviEnd and $err = 1, next;
2028
2068
  $err = 1 if $num;
2029
2069
  $et->Warn('Incorrect RIFF chunk size' . " $pos vs. $riffEnd") if $validate and $pos != $riffEnd;
2030
2070
  last;
@@ -2035,7 +2075,7 @@ sub ProcessRIFF($$)
2035
2075
  $et->OverrideFileType('Extended WEBP',undef,'webp') if $tag eq 'VP8X' and $type eq 'WEBP';
2036
2076
  # special case: construct new tag name from specific LIST type
2037
2077
  if ($tag eq 'LIST') {
2038
- $raf->Read($buff, 4) == 4 or $err=1, last;
2078
+ $raf->Read($buff, 4) == 4 or $err=1, next;
2039
2079
  $pos += 4;
2040
2080
  $tag .= "_$buff";
2041
2081
  $len -= 4; # already read 4 bytes (the LIST type)
@@ -2044,6 +2084,7 @@ sub ProcessRIFF($$)
2044
2084
  }
2045
2085
  $et->VPrint(0, "RIFF '${tag}' chunk ($len bytes of data):\n");
2046
2086
  if ($len <= 0) {
2087
+ $moviEnd and $err = 1, next;
2047
2088
  if ($len < 0) {
2048
2089
  $et->Warn('Invalid chunk length');
2049
2090
  } elsif ($tag eq "\0\0\0\0") {
@@ -2074,7 +2115,7 @@ sub ProcessRIFF($$)
2074
2115
  my $tagInfo = $$tagTbl{$tag};
2075
2116
  # (in LIST_movi chunk: ##db = uncompressed DIB, ##dc = compressed DIB, ##wb = audio data)
2076
2117
  if ($tagInfo or (($verbose or $unknown) and $tag !~ /^(data|idx1|LIST_movi|RIFF|\d{2}(db|dc|wb))$/)) {
2077
- $raf->Read($buff, $len2) == $len2 or $err=1, last;
2118
+ $raf->Read($buff, $len2) == $len2 or $err=1, next;
2078
2119
  if ($hash and $isImageData{$tag}) {
2079
2120
  $hash->add($buff);
2080
2121
  $et->VPrint(0, "$$et{INDENT}(ImageDataHash: '${tag}' chunk, $len2 bytes)\n");
@@ -2100,7 +2141,7 @@ sub ProcessRIFF($$)
2100
2141
  $et->Warn('Incorrect RIFF chunk size') if $validate and $pos - 8 != $riffEnd;
2101
2142
  $riffEnd += $len2 + 8;
2102
2143
  # don't read into RIFF chunk (eg. concatenated video file)
2103
- $raf->Read($buff, 4) == 4 or $err=1, last; # (skip RIFF type word)
2144
+ $raf->Read($buff, 4) == 4 or $err=1, next; # (skip RIFF type word)
2104
2145
  $pos += 4;
2105
2146
  # extract information from remaining file as an embedded file
2106
2147
  $$et{DOC_NUM} = ++$$et{DOC_COUNT};
@@ -2113,18 +2154,21 @@ sub ProcessRIFF($$)
2113
2154
  $et->ImageDataHash($raf, $len2, "'${tag}' chunk");
2114
2155
  }
2115
2156
  if ($tag eq 'LIST_movi' and $ee) {
2116
- $raf->Seek($rewind, 0) or $err = 1, last if $rewind;
2157
+ $raf->Seek($rewind, 0) or $err = 1, next if $rewind;
2158
+ # save end-of-movie offset so we can seek there if we get errors parsing the movie data
2159
+ $moviEnd = $raf->Tell() + $len2;
2117
2160
  next; # parse into movi chunk
2118
2161
  } elsif (not $rewind) {
2119
2162
  if ($len > 0x7fffffff and not $et->Options('LargeFileSupport')) {
2163
+ $tag =~ s/([\0-\x1f\x7f-\xff])/sprintf('\\x%.2x',ord $1)/eg;
2120
2164
  $et->Warn("Stopped parsing at large $tag chunk (LargeFileSupport not set)");
2121
2165
  last;
2122
2166
  }
2123
2167
  if ($validate and $len2) {
2124
2168
  # (must actually try to read something after seeking to detect error)
2125
- $raf->Seek($len2-1, 1) and $raf->Read($buff, 1) == 1 or $err = 1, last;
2169
+ $raf->Seek($len2-1, 1) and $raf->Read($buff, 1) == 1 or $err = 1, next;
2126
2170
  } else {
2127
- $raf->Seek($len2, 1) or $err=1, last;
2171
+ $raf->Seek($len2, 1) or $err=1, next;
2128
2172
  }
2129
2173
  }
2130
2174
  }