@@ -788,6 +788,38 @@ sub check_loadavg {
788
788
# ======================================================================
789
789
# input validation and dispatch
790
790
791
+ # Various hash size-related values.
792
+ my $sha1_len = 40;
793
+ my $sha256_extra_len = 24;
794
+ my $sha256_len = $sha1_len + $sha256_extra_len ;
795
+
796
+ # A regex matching $len hex characters. $len may be a range (e.g. 7,64).
797
+ sub oid_nlen_regex {
798
+ my $len = shift ;
799
+ my $hchr = qr / [0-9a-fA-F]/ ;
800
+ return qr / (?:(?:$hchr ){$len })/ ;
801
+ }
802
+
803
+ # A regex matching two sets of $nlen hex characters, prefixed by the literal
804
+ # string $prefix and with the literal string $infix between them.
805
+ sub oid_nlen_prefix_infix_regex {
806
+ my $nlen = shift ;
807
+ my $prefix = shift ;
808
+ my $infix = shift ;
809
+
810
+ my $rx = oid_nlen_regex($nlen );
811
+
812
+ return qr / ^\Q $prefix \E $rx \Q $infix \E $rx $ / ;
813
+ }
814
+
815
+ # A regex matching a valid object ID.
816
+ our $oid_regex ;
817
+ {
818
+ my $x = oid_nlen_regex($sha1_len );
819
+ my $y = oid_nlen_regex($sha256_extra_len );
820
+ $oid_regex = qr / (?:$x (?:$y )?)/ ;
821
+ }
822
+
791
823
# input parameters can be collected from a variety of sources (presently, CGI
792
824
# and PATH_INFO), so we define an %input_params hash that collects them all
793
825
# together during validation: this allows subsequent uses (e.g. href()) to be
@@ -1516,7 +1548,7 @@ sub is_valid_refname {
1516
1548
1517
1549
return undef unless defined $input ;
1518
1550
# textual hashes are O.K.
1519
- if ($input =~ m / ^[0-9a-fA-F] {40} $ / ) {
1551
+ if ($input =~ m / ^$oid_regex $ / ) {
1520
1552
return 1;
1521
1553
}
1522
1554
# it must be correct pathname
@@ -2028,6 +2060,9 @@ sub file_type_long {
2028
2060
sub format_log_line_html {
2029
2061
my $line = shift ;
2030
2062
2063
+ # Potentially abbreviated OID.
2064
+ my $regex = oid_nlen_regex(" 7,64" );
2065
+
2031
2066
$line = esc_html($line , -nbsp => 1);
2032
2067
$line =~ s {
2033
2068
\b
@@ -2037,10 +2072,10 @@ sub format_log_line_html {
2037
2072
(?<!-) # see strbuf_check_tag_ref(). Tags can't start with -
2038
2073
[A-Za-z0-9.-]+
2039
2074
(?!\. ) # refs can't end with ".", see check_refname_format()
2040
- -g[0-9a-fA-F]{7,40}
2075
+ -g$regex
2041
2076
|
2042
2077
# Just a normal looking Git SHA1
2043
- [0-9a-fA-F]{7,40}
2078
+ $regex
2044
2079
)
2045
2080
\b
2046
2081
} {
@@ -2286,7 +2321,8 @@ sub format_extended_diff_header_line {
2286
2321
' )</span>' ;
2287
2322
}
2288
2323
# match <hash>
2289
- if ($line =~ m / ^index [0-9a-fA-F] {40},[0-9a-fA-F] {40}/ ) {
2324
+ if ($line =~ oid_nlen_prefix_infix_regex($sha1_len , " index " , " ," ) |
2325
+ $line =~ oid_nlen_prefix_infix_regex($sha256_len , " index " , " ," )) {
2290
2326
# can match only for combined diff
2291
2327
$line = ' index ' ;
2292
2328
for (my $i = 0; $i < $diffinfo -> {' nparents' }; $i ++) {
@@ -2308,7 +2344,8 @@ sub format_extended_diff_header_line {
2308
2344
$line .= ' 0' x 7 ;
2309
2345
}
2310
2346
2311
- } elsif ($line =~ m / ^index [0-9a-fA-F] {40}..[0-9a-fA-F] {40}/ ) {
2347
+ } elsif ($line =~ oid_nlen_prefix_infix_regex($sha1_len , " index " , " .." ) |
2348
+ $line =~ oid_nlen_prefix_infix_regex($sha256_len , " index " , " .." )) {
2312
2349
# can match only for ordinary diff
2313
2350
my ($from_link , $to_link );
2314
2351
if ($from -> {' href' }) {
@@ -2834,7 +2871,7 @@ sub git_get_hash_by_path {
2834
2871
}
2835
2872
2836
2873
# '100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa panic.c'
2837
- $line =~ m / ^([0-9]+) (.+) ([0-9a-fA-F]{40} )\t / ;
2874
+ $line =~ m / ^([0-9]+) (.+) ($oid_regex )\t / ;
2838
2875
if (defined $type && $type ne $2 ) {
2839
2876
# type doesn't match
2840
2877
return undef ;
@@ -3333,7 +3370,7 @@ sub git_get_references {
3333
3370
3334
3371
while (my $line = <$fd >) {
3335
3372
chomp $line ;
3336
- if ($line =~ m ! ^([0-9a-fA-F]{40} )\s refs/($type .*)$ ! ) {
3373
+ if ($line =~ m ! ^($oid_regex )\s refs/($type .*)$ ! ) {
3337
3374
if (defined $refs {$1 }) {
3338
3375
push @{$refs {$1 }}, $2 ;
3339
3376
} else {
@@ -3407,7 +3444,7 @@ sub parse_tag {
3407
3444
$tag {' id' } = $tag_id ;
3408
3445
while (my $line = <$fd >) {
3409
3446
chomp $line ;
3410
- if ($line =~ m / ^object ([0-9a-fA-F]{40} )$ / ) {
3447
+ if ($line =~ m / ^object ($oid_regex )$ / ) {
3411
3448
$tag {' object' } = $1 ;
3412
3449
} elsif ($line =~ m / ^type (.+)$ / ) {
3413
3450
$tag {' type' } = $1 ;
@@ -3451,15 +3488,15 @@ sub parse_commit_text {
3451
3488
}
3452
3489
3453
3490
my $header = shift @commit_lines ;
3454
- if ($header !~ m / ^[0-9a-fA-F] {40} / ) {
3491
+ if ($header !~ m / ^$oid_regex / ) {
3455
3492
return ;
3456
3493
}
3457
3494
($co {' id' }, my @parents ) = split ' ' , $header ;
3458
3495
while (my $line = shift @commit_lines ) {
3459
3496
last if $line eq " \n " ;
3460
- if ($line =~ m / ^tree ([0-9a-fA-F]{40} )$ / ) {
3497
+ if ($line =~ m / ^tree ($oid_regex )$ / ) {
3461
3498
$co {' tree' } = $1 ;
3462
- } elsif ((!defined $withparents ) && ($line =~ m / ^parent ([0-9a-fA-F]{40} )$ / )) {
3499
+ } elsif ((!defined $withparents ) && ($line =~ m / ^parent ($oid_regex )$ / )) {
3463
3500
push @parents , $1 ;
3464
3501
} elsif ($line =~ m / ^author (.*) ([0-9]+) (.*)$ / ) {
3465
3502
$co {' author' } = to_utf8($1 );
@@ -3591,7 +3628,7 @@ sub parse_difftree_raw_line {
3591
3628
3592
3629
# ':100644 100644 03b218260e99b78c6df0ed378e59ed9205ccc96d 3b93d5e7cc7f7dd4ebed13a5cc1a4ad976fc94d8 M ls-files.c'
3593
3630
# ':100644 100644 7f9281985086971d3877aca27704f2aaf9c448ce bc190ebc71bbd923f2b728e505408f5e54bd073a M rev-tree.c'
3594
- if ($line =~ m / ^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40} ) ([0-9a-fA-F]{40} ) (.)([0-9]{0,3})\t (.*)$ / ) {
3631
+ if ($line =~ m / ^:([0-7]{6}) ([0-7]{6}) ($oid_regex ) ($oid_regex ) (.)([0-9]{0,3})\t (.*)$ / ) {
3595
3632
$res {' from_mode' } = $1 ;
3596
3633
$res {' to_mode' } = $2 ;
3597
3634
$res {' from_id' } = $3 ;
@@ -3606,7 +3643,7 @@ sub parse_difftree_raw_line {
3606
3643
}
3607
3644
# '::100755 100755 100755 60e79ca1b01bc8b057abe17ddab484699a7f5fdb 94067cc5f73388f33722d52ae02f44692bc07490 94067cc5f73388f33722d52ae02f44692bc07490 MR git-gui/git-gui.sh'
3608
3645
# combined diff (for merge commit)
3609
- elsif ($line =~ s / ^(::+)((?:[0-7]{6} )+)((?:[0-9a-fA-F]{40} )+)([a-zA-Z]+)\t (.*)$// ) {
3646
+ elsif ($line =~ s / ^(::+)((?:[0-7]{6} )+)((?:$oid_regex )+)([a-zA-Z]+)\t (.*)$// ) {
3610
3647
$res {' nparents' } = length ($1 );
3611
3648
$res {' from_mode' } = [ split (' ' , $2 ) ];
3612
3649
$res {' to_mode' } = pop @{$res {' from_mode' }};
@@ -3616,7 +3653,7 @@ sub parse_difftree_raw_line {
3616
3653
$res {' to_file' } = unquote($5 );
3617
3654
}
3618
3655
# 'c512b523472485aef4fff9e57b229d9d243c967f'
3619
- elsif ($line =~ m / ^([0-9a-fA-F]{40} )$ / ) {
3656
+ elsif ($line =~ m / ^($oid_regex )$ / ) {
3620
3657
$res {' commit' } = $1 ;
3621
3658
}
3622
3659
@@ -3644,7 +3681,7 @@ sub parse_ls_tree_line {
3644
3681
3645
3682
if ($opts {' -l' }) {
3646
3683
# '100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa 16717 panic.c'
3647
- $line =~ m / ^([0-9]+) (.+) ([0-9a-fA-F]{40} ) +(-|[0-9]+)\t (.+)$ / s ;
3684
+ $line =~ m / ^([0-9]+) (.+) ($oid_regex ) +(-|[0-9]+)\t (.+)$ / s ;
3648
3685
3649
3686
$res {' mode' } = $1 ;
3650
3687
$res {' type' } = $2 ;
@@ -3657,7 +3694,7 @@ sub parse_ls_tree_line {
3657
3694
}
3658
3695
} else {
3659
3696
# '100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa panic.c'
3660
- $line =~ m / ^([0-9]+) (.+) ([0-9a-fA-F]{40} )\t (.+)$ / s ;
3697
+ $line =~ m / ^([0-9]+) (.+) ($oid_regex )\t (.+)$ / s ;
3661
3698
3662
3699
$res {' mode' } = $1 ;
3663
3700
$res {' type' } = $2 ;
@@ -4799,7 +4836,7 @@ sub fill_from_file_info {
4799
4836
sub is_deleted {
4800
4837
my $diffinfo = shift ;
4801
4838
4802
- return $diffinfo -> {' to_id' } eq (' 0' x 40 );
4839
+ return $diffinfo -> {' to_id' } eq (' 0' x 40 ) || $diffinfo -> { ' to_id ' } eq ( ' 0 ' x 64 ) ;
4803
4840
}
4804
4841
4805
4842
# does patch correspond to [previous] difftree raw line
@@ -6285,7 +6322,7 @@ sub git_search_changes {
6285
6322
-class => " list subject" },
6286
6323
chop_and_escape_str($co {' title' }, 50) . " <br/>" );
6287
6324
} elsif (defined $set {' to_id' }) {
6288
- next if ( $ set{ ' to_id ' } =~ m / ^0{40} $ / );
6325
+ next if is_deleted(\ % set );
6289
6326
6290
6327
print $cgi -> a({-href => href(action => " blob" , hash_base => $co {' id' },
6291
6328
hash => $set {' to_id' }, file_name => $set {' to_file' }),
@@ -6829,7 +6866,7 @@ sub git_blame_common {
6829
6866
# the header: <SHA-1> <src lineno> <dst lineno> [<lines in group>]
6830
6867
# no <lines in group> for subsequent lines in group of lines
6831
6868
my ($full_rev , $orig_lineno , $lineno , $group_size ) =
6832
- ($line =~ / ^([0-9a-f]{40} ) (\d +) (\d +)(?: (\d +))?$ / );
6869
+ ($line =~ / ^($oid_regex ) (\d +) (\d +)(?: (\d +))?$ / );
6833
6870
if (!exists $metainfo {$full_rev }) {
6834
6871
$metainfo {$full_rev } = { ' nprevious' => 0 };
6835
6872
}
@@ -6879,7 +6916,7 @@ sub git_blame_common {
6879
6916
}
6880
6917
# 'previous' <sha1 of parent commit> <filename at commit>
6881
6918
if (exists $meta -> {' previous' } &&
6882
- $meta -> {' previous' } =~ / ^([a-fA-F0-9]{40} ) (.*)$ / ) {
6919
+ $meta -> {' previous' } =~ / ^($oid_regex ) (.*)$ / ) {
6883
6920
$meta -> {' parent' } = $1 ;
6884
6921
$meta -> {' file_parent' } = unquote($2 );
6885
6922
}
@@ -6996,7 +7033,7 @@ sub git_blob_plain {
6996
7033
} else {
6997
7034
die_error(400, " No file name defined" );
6998
7035
}
6999
- } elsif ($hash =~ m / ^[0-9a-fA-F] {40} $ / ) {
7036
+ } elsif ($hash =~ m / ^$oid_regex $ / ) {
7000
7037
# blobs defined by non-textual hash id's can be cached
7001
7038
$expires = " +1d" ;
7002
7039
}
@@ -7057,7 +7094,7 @@ sub git_blob {
7057
7094
} else {
7058
7095
die_error(400, " No file name defined" );
7059
7096
}
7060
- } elsif ($hash =~ m / ^[0-9a-fA-F] {40} $ / ) {
7097
+ } elsif ($hash =~ m / ^$oid_regex $ / ) {
7061
7098
# blobs defined by non-textual hash id's can be cached
7062
7099
$expires = " +1d" ;
7063
7100
}
@@ -7515,7 +7552,7 @@ sub git_commit {
7515
7552
7516
7553
# non-textual hash id's can be cached
7517
7554
my $expires ;
7518
- if ($hash =~ m / ^[0-9a-fA-F] {40} $ / ) {
7555
+ if ($hash =~ m / ^$oid_regex $ / ) {
7519
7556
$expires = " +1d" ;
7520
7557
}
7521
7558
my $refs = git_get_references();
@@ -7609,7 +7646,7 @@ sub git_object {
7609
7646
close $fd ;
7610
7647
7611
7648
# '100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa panic.c'
7612
- unless ($line && $line =~ m / ^([0-9]+) (.+) ([0-9a-fA-F]{40} )\t / ) {
7649
+ unless ($line && $line =~ m / ^([0-9]+) (.+) ($oid_regex )\t / ) {
7613
7650
die_error(404, " File or directory for given base does not exist" );
7614
7651
}
7615
7652
$type = $2 ;
@@ -7649,7 +7686,7 @@ sub git_blobdiff {
7649
7686
or die_error(404, " Blob diff not found" );
7650
7687
7651
7688
} elsif (defined $hash &&
7652
- $hash =~ / [0-9a-fA-F]{40} / ) {
7689
+ $hash =~ $oid_regex ) {
7653
7690
# try to find filename from $hash
7654
7691
7655
7692
# read filtered raw output
@@ -7659,7 +7696,7 @@ sub git_blobdiff {
7659
7696
@difftree =
7660
7697
# ':100644 100644 03b21826... 3b93d5e7... M ls-files.c'
7661
7698
# $hash == to_id
7662
- grep { / ^:[0-7]{6} [0-7]{6} [0-9a-fA-F]{40} $hash / }
7699
+ grep { / ^:[0-7]{6} [0-7]{6} $oid_regex $hash / }
7663
7700
map { chomp ; $_ } <$fd >;
7664
7701
close $fd
7665
7702
or die_error(404, " Reading git-diff-tree failed" );
@@ -7682,8 +7719,8 @@ sub git_blobdiff {
7682
7719
$hash ||= $diffinfo {' to_id' };
7683
7720
7684
7721
# non-textual hash id's can be cached
7685
- if ($hash_base =~ m / ^[0-9a-fA-F] {40} $ / &&
7686
- $hash_parent_base =~ m / ^[0-9a-fA-F] {40} $ / ) {
7722
+ if ($hash_base =~ m / ^$oid_regex $ / &&
7723
+ $hash_parent_base =~ m / ^$oid_regex $ / ) {
7687
7724
$expires = ' +1d' ;
7688
7725
}
7689
7726
@@ -7819,7 +7856,7 @@ sub git_commitdiff {
7819
7856
$hash_parent ne ' -c' && $hash_parent ne ' --cc' ) {
7820
7857
# commitdiff with two commits given
7821
7858
my $hash_parent_short = $hash_parent ;
7822
- if ($hash_parent =~ m / ^[0-9a-fA-F] {40} $ / ) {
7859
+ if ($hash_parent =~ m / ^$oid_regex $ / ) {
7823
7860
$hash_parent_short = substr ($hash_parent , 0, 7);
7824
7861
}
7825
7862
$formats_nav .=
@@ -7928,7 +7965,7 @@ sub git_commitdiff {
7928
7965
7929
7966
# non-textual hash id's can be cached
7930
7967
my $expires ;
7931
- if ($hash =~ m / ^[0-9a-fA-F] {40} $ / ) {
7968
+ if ($hash =~ m / ^$oid_regex $ / ) {
7932
7969
$expires = " +1d" ;
7933
7970
}
7934
7971
0 commit comments