~ubuntu-branches/ubuntu/natty/amavisd-new/natty

« back to all changes in this revision

Viewing changes to JpegTester.pm

  • Committer: Bazaar Package Importer
  • Author(s): Christian Perrier
  • Date: 2007-02-24 19:27:53 UTC
  • mfrom: (3.1.7 feisty)
  • Revision ID: james.westby@ubuntu.com-20070224192753-fvvima53q1jrp34x
Tags: 1:2.4.2-6.1
* Non-maintainer upload to fix pending l10n issues.
* Debconf translations
  - Remove extra debian/po/de.po~
  - Convert all translation files to UTF-8
  - Russian. Closes: #405243
  - Spanish. Closes: #408734
  - Italian. Closes: #409831
* Add very simple LSB headers to init scripts

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package JpegTester;
 
2
# Author: Mark Martinec <mark.martinec@ijs.si>, 2004-10;
 
3
# The (new)BSD license applies to this package JpegTester;
 
4
use strict;
 
5
use re 'taint';
 
6
 
 
7
use vars qw($buf $buf_l $buf_ofs);
 
8
sub makeTwo($) {   # ensure at least two characters in $buf, except near eof
 
9
  my($fh) = @_;
 
10
  $buf_l>=0 or die "jpeg: Panic, program error1, pos=$buf_ofs";
 
11
  if ($buf_l<2) {
 
12
    my($len) = sysread($fh,$buf,2048,$buf_l);  # 2k is about the optimum size
 
13
    defined $len or die "jpeg: Can't read: $!\n";
 
14
    $buf_l += $len;
 
15
  }
 
16
}
 
17
sub takeN($$) {    # swallow n characters
 
18
  my($fh,$n) = @_; my($err) = undef;
 
19
  for ($buf_l>=2||makeTwo($fh); $n>0; ) {
 
20
    if ($buf_l<=0) { $err = "Truncated by $n bytes or more"; last }
 
21
    if ($n >= $buf_l) { $n -= $buf_l; $buf_ofs += $buf_l; $buf = '' }
 
22
    else { $buf = substr($buf,$n); $buf_ofs += $n; $n = 0 }
 
23
    $buf_l = length($buf);  $buf_l>=2 || makeTwo($fh);
 
24
  }
 
25
  $err;
 
26
}
 
27
sub takeECS($) {   # quickly swallow entropy-coded data segment
 
28
  my($fh) = @_;
 
29
  for ($buf_l>=2||makeTwo($fh); $buf_l>0; ) {
 
30
    if    ($buf =~ s/^([^\xff]+)//)  { $buf_ofs += length($1) }
 
31
    elsif ($buf =~ s/^(\xff\x00)+//) { $buf_ofs += length($1) }
 
32
    else { last }
 
33
#   last unless $buf =~ s/^(?: [^\xff] | \xff \x00 )+//x;  # Perl Bus error
 
34
    $buf_l = length($buf);  $buf_l>=2 || makeTwo($fh);
 
35
  }
 
36
}
 
37
sub takeFill($) {  # swallow fill bytes before marker
 
38
  my($fh) = @_;
 
39
  for (makeTwo($fh); $buf_l>0; $buf_l=length($buf),makeTwo($fh)) {
 
40
    if ($buf =~ s/^ \xff+ (?= \xff )//x) { $buf_ofs += length($1) }
 
41
    else { last }
 
42
  }
 
43
}
 
44
sub takeTail($) {  # swallow common junk after EOI
 
45
  my($fh) = @_;
 
46
  for (makeTwo($fh); $buf_l>0; $buf_l=length($buf),makeTwo($fh)) {
 
47
    if ($buf =~ s/^[\x00\xff]+//) { $buf_ofs += length($1) }
 
48
    else { last }
 
49
  }
 
50
}
 
51
 
 
52
# exit status: 0:clean; 1:exploit; 2:corrupted
 
53
sub test_jpeg($;@) {
 
54
  my($fn) = @_;  # file name to be checked
 
55
  local(*F); my($fh) = \*F;
 
56
  open($fh,"<$fn") or die "jpeg: Can't open file $fn for reading: $!";
 
57
  binmode($fh) or die "jpeg: Can't set binmode on $fn: $!";
 
58
  $buf = ''; $buf_l = 0; $buf_ofs = 0; makeTwo($fh); my(@r) = (0,"jpeg ok");
 
59
  if ($buf !~ /^\xff\xd8/) { @r = (0,"not jpeg") }
 
60
  else { takeN($fh,2);  if ($buf !~ /^\xff/) { @r = (0,"not jpeg") } }
 
61
  if ($r[1] eq "jpeg ok") {
 
62
    my($ecs_ok) = 0; local($1);
 
63
    for (;;) {  # keep at least 2 chars in buff except near eof
 
64
      if ($buf_l<=0 || $buf eq "\xff") {
 
65
        @r = (2,"Truncated, no EOI, pos=$buf_ofs")  if !$r[0];
 
66
        last;
 
67
      } elsif ($buf =~ /^( [^\xff] | \xff \x00 )/x) {  # ecs
 
68
        @r = (2,"Unexpected entropy-coded data segment, pos=$buf_ofs")
 
69
          if !$ecs_ok && !$r[0];
 
70
        takeECS($fh);  $ecs_ok = 0;
 
71
      } elsif ($buf =~ /^ \xff+ (?= \xff ) /x) {     # fill bytes before marker
 
72
        takeFill($fh); $ecs_ok = 0;
 
73
      } elsif ($buf =~ /^ \xff ([^\x00\xff]) /x) {   # marker
 
74
        my($m) = $1; takeN($fh,2);
 
75
        if    ($m =~ /[\xd0-\xd7]/) {    # RSTi
 
76
#         printf("marker segm, pos=%d, marker=0x%02X\n", $buf_ofs,ord($m));
 
77
          $ecs_ok = 1;
 
78
        } elsif ($m =~ /[\x01\xd8]/) {   # TEM, SOI
 
79
#         printf("marker segm, pos=%d, marker=0x%02X\n", $buf_ofs,ord($m));
 
80
          $ecs_ok = 0;
 
81
        }
 
82
        elsif ($m eq "\xd9") {  # EOI
 
83
#         printf("marker segm, pos=%d, marker=0x%02X\n", $buf_ofs,ord($m));
 
84
          takeFill($fh); $ecs_ok = 0;
 
85
          @r = (2,"Trailing garbage, pos=$buf_ofs")  if $buf_l>0 && !$r[0];
 
86
          last;
 
87
        } else {  # marker segment
 
88
          $ecs_ok = $m eq "\xda";  # SOS
 
89
          my($len) = unpack("n",substr($buf,0,2));
 
90
#         printf("marker segm len %d, pos=%d, marker=0x%02X\n", $len,$buf_ofs,ord($m));
 
91
          @r = (1,sprintf("Invalid marker segm len %d, pos=%d, marker=0x%02X",
 
92
                          $len,$buf_ofs,ord($m)) )  if $len<2;
 
93
          my($err) = takeN($fh,$len);
 
94
          @r = (2,"$err, pos=$buf_ofs")  if defined $err && !$r[0];
 
95
        }
 
96
      } else { die "jpeg: Panic, program error2, pos=$buf_ofs" }
 
97
      $buf_l>=2 || makeTwo($fh);
 
98
    }
 
99
  }
 
100
  close($fh) or die "jpeg: Can't close $fn: $!";
 
101
  $r[1] = "bad jpeg: ".$r[1]  if $r[0];
 
102
  @r;
 
103
}
 
104
 
 
105
1;  # insure a defined return