@@ -24,7 +24,7 @@ static const char git_attr__unknown[] = "(builtin)unknown";
24
24
#define ATTR__UNKNOWN git_attr__unknown
25
25
26
26
struct git_attr {
27
- int attr_nr ; /* unique attribute number */
27
+ unsigned int attr_nr ; /* unique attribute number */
28
28
char name [FLEX_ARRAY ]; /* attribute name */
29
29
};
30
30
@@ -206,7 +206,7 @@ static void report_invalid_attr(const char *name, size_t len,
206
206
* dictionary. If no entry is found, create a new attribute and store it in
207
207
* the dictionary.
208
208
*/
209
- static const struct git_attr * git_attr_internal (const char * name , int namelen )
209
+ static const struct git_attr * git_attr_internal (const char * name , size_t namelen )
210
210
{
211
211
struct git_attr * a ;
212
212
@@ -222,8 +222,8 @@ static const struct git_attr *git_attr_internal(const char *name, int namelen)
222
222
a -> attr_nr = hashmap_get_size (& g_attr_hashmap .map );
223
223
224
224
attr_hashmap_add (& g_attr_hashmap , a -> name , namelen , a );
225
- assert (a -> attr_nr ==
226
- ( hashmap_get_size ( & g_attr_hashmap . map ) - 1 ));
225
+ if (a -> attr_nr != hashmap_get_size ( & g_attr_hashmap . map ) - 1 )
226
+ die ( _ ( "unable to add additional attribute" ));
227
227
}
228
228
229
229
hashmap_unlock (& g_attr_hashmap );
@@ -268,7 +268,7 @@ struct match_attr {
268
268
const struct git_attr * attr ;
269
269
} u ;
270
270
char is_macro ;
271
- unsigned num_attr ;
271
+ size_t num_attr ;
272
272
struct attr_state state [FLEX_ARRAY ];
273
273
};
274
274
@@ -289,7 +289,7 @@ static const char *parse_attr(const char *src, int lineno, const char *cp,
289
289
struct attr_state * e )
290
290
{
291
291
const char * ep , * equals ;
292
- int len ;
292
+ size_t len ;
293
293
294
294
ep = cp + strcspn (cp , blank );
295
295
equals = strchr (cp , '=' );
@@ -333,8 +333,7 @@ static const char *parse_attr(const char *src, int lineno, const char *cp,
333
333
static struct match_attr * parse_attr_line (const char * line , const char * src ,
334
334
int lineno , unsigned flags )
335
335
{
336
- int namelen ;
337
- int num_attr , i ;
336
+ size_t namelen , num_attr , i ;
338
337
const char * cp , * name , * states ;
339
338
struct match_attr * res = NULL ;
340
339
int is_macro ;
@@ -345,6 +344,11 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
345
344
return NULL ;
346
345
name = cp ;
347
346
347
+ if (strlen (line ) >= ATTR_MAX_LINE_LENGTH ) {
348
+ warning (_ ("ignoring overly long attributes line %d" ), lineno );
349
+ return NULL ;
350
+ }
351
+
348
352
if (* cp == '"' && !unquote_c_style (& pattern , name , & states )) {
349
353
name = pattern .buf ;
350
354
namelen = pattern .len ;
@@ -381,10 +385,9 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
381
385
goto fail_return ;
382
386
}
383
387
384
- res = xcalloc (1 ,
385
- sizeof (* res ) +
386
- sizeof (struct attr_state ) * num_attr +
387
- (is_macro ? 0 : namelen + 1 ));
388
+ res = xcalloc (1 , st_add3 (sizeof (* res ),
389
+ st_mult (sizeof (struct attr_state ), num_attr ),
390
+ is_macro ? 0 : namelen + 1 ));
388
391
if (is_macro ) {
389
392
res -> u .attr = git_attr_internal (name , namelen );
390
393
} else {
@@ -447,11 +450,12 @@ struct attr_stack {
447
450
448
451
static void attr_stack_free (struct attr_stack * e )
449
452
{
450
- int i ;
453
+ unsigned i ;
451
454
free (e -> origin );
452
455
for (i = 0 ; i < e -> num_matches ; i ++ ) {
453
456
struct match_attr * a = e -> attrs [i ];
454
- int j ;
457
+ size_t j ;
458
+
455
459
for (j = 0 ; j < a -> num_attr ; j ++ ) {
456
460
const char * setto = a -> state [j ].setto ;
457
461
if (setto == ATTR__TRUE ||
@@ -660,8 +664,8 @@ static void handle_attr_line(struct attr_stack *res,
660
664
a = parse_attr_line (line , src , lineno , flags );
661
665
if (!a )
662
666
return ;
663
- ALLOC_GROW (res -> attrs , res -> num_matches + 1 , res -> alloc );
664
- res -> attrs [res -> num_matches ++ ] = a ;
667
+ ALLOC_GROW_BY (res -> attrs , res -> num_matches , 1 , res -> alloc );
668
+ res -> attrs [res -> num_matches - 1 ] = a ;
665
669
}
666
670
667
671
static struct attr_stack * read_attr_from_array (const char * * list )
@@ -701,11 +705,12 @@ void git_attr_set_direction(enum git_attr_direction new_direction)
701
705
702
706
static struct attr_stack * read_attr_from_file (const char * path , unsigned flags )
703
707
{
708
+ struct strbuf buf = STRBUF_INIT ;
704
709
int fd ;
705
710
FILE * fp ;
706
711
struct attr_stack * res ;
707
- char buf [2048 ];
708
712
int lineno = 0 ;
713
+ struct stat st ;
709
714
710
715
if (flags & READ_ATTR_NOFOLLOW )
711
716
fd = open_nofollow (path , O_RDONLY );
@@ -717,15 +722,26 @@ static struct attr_stack *read_attr_from_file(const char *path, unsigned flags)
717
722
return NULL ;
718
723
}
719
724
fp = xfdopen (fd , "r" );
725
+ if (fstat (fd , & st )) {
726
+ warning_errno (_ ("cannot fstat gitattributes file '%s'" ), path );
727
+ fclose (fp );
728
+ return NULL ;
729
+ }
730
+ if (st .st_size >= ATTR_MAX_FILE_SIZE ) {
731
+ warning (_ ("ignoring overly large gitattributes file '%s'" ), path );
732
+ fclose (fp );
733
+ return NULL ;
734
+ }
720
735
721
736
CALLOC_ARRAY (res , 1 );
722
- while (fgets (buf , sizeof (buf ), fp )) {
723
- char * bufp = buf ;
724
- if (!lineno )
725
- skip_utf8_bom (& bufp , strlen (bufp ));
726
- handle_attr_line (res , bufp , path , ++ lineno , flags );
737
+ while (strbuf_getline (& buf , fp ) != EOF ) {
738
+ if (!lineno && starts_with (buf .buf , utf8_bom ))
739
+ strbuf_remove (& buf , 0 , strlen (utf8_bom ));
740
+ handle_attr_line (res , buf .buf , path , ++ lineno , flags );
727
741
}
742
+
728
743
fclose (fp );
744
+ strbuf_release (& buf );
729
745
return res ;
730
746
}
731
747
@@ -736,6 +752,7 @@ static struct attr_stack *read_attr_from_index(struct index_state *istate,
736
752
struct attr_stack * res ;
737
753
char * buf , * sp ;
738
754
int lineno = 0 ;
755
+ size_t size ;
739
756
740
757
if (!istate )
741
758
return NULL ;
@@ -754,9 +771,13 @@ static struct attr_stack *read_attr_from_index(struct index_state *istate,
754
771
if (!path_in_cone_mode_sparse_checkout (path , istate ))
755
772
return NULL ;
756
773
757
- buf = read_blob_data_from_index (istate , path , NULL );
774
+ buf = read_blob_data_from_index (istate , path , & size );
758
775
if (!buf )
759
776
return NULL ;
777
+ if (size >= ATTR_MAX_FILE_SIZE ) {
778
+ warning (_ ("ignoring overly large gitattributes blob '%s'" ), path );
779
+ return NULL ;
780
+ }
760
781
761
782
CALLOC_ARRAY (res , 1 );
762
783
for (sp = buf ; * sp ; ) {
@@ -999,12 +1020,12 @@ static int macroexpand_one(struct all_attrs_item *all_attrs, int nr, int rem);
999
1020
static int fill_one (struct all_attrs_item * all_attrs ,
1000
1021
const struct match_attr * a , int rem )
1001
1022
{
1002
- int i ;
1023
+ size_t i ;
1003
1024
1004
- for (i = a -> num_attr - 1 ; rem > 0 && i >= 0 ; i -- ) {
1005
- const struct git_attr * attr = a -> state [i ].attr ;
1025
+ for (i = a -> num_attr ; rem > 0 && i > 0 ; i -- ) {
1026
+ const struct git_attr * attr = a -> state [i - 1 ].attr ;
1006
1027
const char * * n = & (all_attrs [attr -> attr_nr ].value );
1007
- const char * v = a -> state [i ].setto ;
1028
+ const char * v = a -> state [i - 1 ].setto ;
1008
1029
1009
1030
if (* n == ATTR__UNKNOWN ) {
1010
1031
* n = v ;
@@ -1020,11 +1041,11 @@ static int fill(const char *path, int pathlen, int basename_offset,
1020
1041
struct all_attrs_item * all_attrs , int rem )
1021
1042
{
1022
1043
for (; rem > 0 && stack ; stack = stack -> prev ) {
1023
- int i ;
1044
+ unsigned i ;
1024
1045
const char * base = stack -> origin ? stack -> origin : "" ;
1025
1046
1026
- for (i = stack -> num_matches - 1 ; 0 < rem && 0 <= i ; i -- ) {
1027
- const struct match_attr * a = stack -> attrs [i ];
1047
+ for (i = stack -> num_matches ; 0 < rem && 0 < i ; i -- ) {
1048
+ const struct match_attr * a = stack -> attrs [i - 1 ];
1028
1049
if (a -> is_macro )
1029
1050
continue ;
1030
1051
if (path_matches (path , pathlen , basename_offset ,
@@ -1055,11 +1076,11 @@ static void determine_macros(struct all_attrs_item *all_attrs,
1055
1076
const struct attr_stack * stack )
1056
1077
{
1057
1078
for (; stack ; stack = stack -> prev ) {
1058
- int i ;
1059
- for (i = stack -> num_matches - 1 ; i >= 0 ; i -- ) {
1060
- const struct match_attr * ma = stack -> attrs [i ];
1079
+ unsigned i ;
1080
+ for (i = stack -> num_matches ; i > 0 ; i -- ) {
1081
+ const struct match_attr * ma = stack -> attrs [i - 1 ];
1061
1082
if (ma -> is_macro ) {
1062
- int n = ma -> u .attr -> attr_nr ;
1083
+ unsigned int n = ma -> u .attr -> attr_nr ;
1063
1084
if (!all_attrs [n ].macro ) {
1064
1085
all_attrs [n ].macro = ma ;
1065
1086
}
@@ -1111,7 +1132,7 @@ void git_check_attr(struct index_state *istate,
1111
1132
collect_some_attrs (istate , path , check );
1112
1133
1113
1134
for (i = 0 ; i < check -> nr ; i ++ ) {
1114
- size_t n = check -> items [i ].attr -> attr_nr ;
1135
+ unsigned int n = check -> items [i ].attr -> attr_nr ;
1115
1136
const char * value = check -> all_attrs [n ].value ;
1116
1137
if (value == ATTR__UNKNOWN )
1117
1138
value = ATTR__UNSET ;
0 commit comments