@@ -29,7 +29,7 @@ static const char git_attr__unknown[] = "(builtin)unknown";
29
29
#endif
30
30
31
31
struct git_attr {
32
- int attr_nr ; /* unique attribute number */
32
+ unsigned int attr_nr ; /* unique attribute number */
33
33
char name [FLEX_ARRAY ]; /* attribute name */
34
34
};
35
35
@@ -211,7 +211,7 @@ static void report_invalid_attr(const char *name, size_t len,
211
211
* dictionary. If no entry is found, create a new attribute and store it in
212
212
* the dictionary.
213
213
*/
214
- static const struct git_attr * git_attr_internal (const char * name , int namelen )
214
+ static const struct git_attr * git_attr_internal (const char * name , size_t namelen )
215
215
{
216
216
struct git_attr * a ;
217
217
@@ -227,8 +227,8 @@ static const struct git_attr *git_attr_internal(const char *name, int namelen)
227
227
a -> attr_nr = hashmap_get_size (& g_attr_hashmap .map );
228
228
229
229
attr_hashmap_add (& g_attr_hashmap , a -> name , namelen , a );
230
- assert (a -> attr_nr ==
231
- ( hashmap_get_size ( & g_attr_hashmap . map ) - 1 ));
230
+ if (a -> attr_nr != hashmap_get_size ( & g_attr_hashmap . map ) - 1 )
231
+ die ( _ ( "unable to add additional attribute" ));
232
232
}
233
233
234
234
hashmap_unlock (& g_attr_hashmap );
@@ -273,7 +273,7 @@ struct match_attr {
273
273
const struct git_attr * attr ;
274
274
} u ;
275
275
char is_macro ;
276
- unsigned num_attr ;
276
+ size_t num_attr ;
277
277
struct attr_state state [FLEX_ARRAY ];
278
278
};
279
279
@@ -294,7 +294,7 @@ static const char *parse_attr(const char *src, int lineno, const char *cp,
294
294
struct attr_state * e )
295
295
{
296
296
const char * ep , * equals ;
297
- int len ;
297
+ size_t len ;
298
298
299
299
ep = cp + strcspn (cp , blank );
300
300
equals = strchr (cp , '=' );
@@ -338,8 +338,7 @@ static const char *parse_attr(const char *src, int lineno, const char *cp,
338
338
static struct match_attr * parse_attr_line (const char * line , const char * src ,
339
339
int lineno , unsigned flags )
340
340
{
341
- int namelen ;
342
- int num_attr , i ;
341
+ size_t namelen , num_attr , i ;
343
342
const char * cp , * name , * states ;
344
343
struct match_attr * res = NULL ;
345
344
int is_macro ;
@@ -350,6 +349,11 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
350
349
return NULL ;
351
350
name = cp ;
352
351
352
+ if (strlen (line ) >= ATTR_MAX_LINE_LENGTH ) {
353
+ warning (_ ("ignoring overly long attributes line %d" ), lineno );
354
+ return NULL ;
355
+ }
356
+
353
357
if (* cp == '"' && !unquote_c_style (& pattern , name , & states )) {
354
358
name = pattern .buf ;
355
359
namelen = pattern .len ;
@@ -386,10 +390,9 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
386
390
goto fail_return ;
387
391
}
388
392
389
- res = xcalloc (1 ,
390
- sizeof (* res ) +
391
- sizeof (struct attr_state ) * num_attr +
392
- (is_macro ? 0 : namelen + 1 ));
393
+ res = xcalloc (1 , st_add3 (sizeof (* res ),
394
+ st_mult (sizeof (struct attr_state ), num_attr ),
395
+ is_macro ? 0 : namelen + 1 ));
393
396
if (is_macro ) {
394
397
res -> u .attr = git_attr_internal (name , namelen );
395
398
} else {
@@ -452,11 +455,12 @@ struct attr_stack {
452
455
453
456
static void attr_stack_free (struct attr_stack * e )
454
457
{
455
- int i ;
458
+ unsigned i ;
456
459
free (e -> origin );
457
460
for (i = 0 ; i < e -> num_matches ; i ++ ) {
458
461
struct match_attr * a = e -> attrs [i ];
459
- int j ;
462
+ size_t j ;
463
+
460
464
for (j = 0 ; j < a -> num_attr ; j ++ ) {
461
465
const char * setto = a -> state [j ].setto ;
462
466
if (setto == ATTR__TRUE ||
@@ -665,8 +669,8 @@ static void handle_attr_line(struct attr_stack *res,
665
669
a = parse_attr_line (line , src , lineno , flags );
666
670
if (!a )
667
671
return ;
668
- ALLOC_GROW (res -> attrs , res -> num_matches + 1 , res -> alloc );
669
- res -> attrs [res -> num_matches ++ ] = a ;
672
+ ALLOC_GROW_BY (res -> attrs , res -> num_matches , 1 , res -> alloc );
673
+ res -> attrs [res -> num_matches - 1 ] = a ;
670
674
}
671
675
672
676
static struct attr_stack * read_attr_from_array (const char * * list )
@@ -706,11 +710,12 @@ void git_attr_set_direction(enum git_attr_direction new_direction)
706
710
707
711
static struct attr_stack * read_attr_from_file (const char * path , unsigned flags )
708
712
{
713
+ struct strbuf buf = STRBUF_INIT ;
709
714
int fd ;
710
715
FILE * fp ;
711
716
struct attr_stack * res ;
712
- char buf [2048 ];
713
717
int lineno = 0 ;
718
+ struct stat st ;
714
719
715
720
if (flags & READ_ATTR_NOFOLLOW )
716
721
fd = open_nofollow (path , O_RDONLY );
@@ -722,15 +727,26 @@ static struct attr_stack *read_attr_from_file(const char *path, unsigned flags)
722
727
return NULL ;
723
728
}
724
729
fp = xfdopen (fd , "r" );
730
+ if (fstat (fd , & st )) {
731
+ warning_errno (_ ("cannot fstat gitattributes file '%s'" ), path );
732
+ fclose (fp );
733
+ return NULL ;
734
+ }
735
+ if (st .st_size >= ATTR_MAX_FILE_SIZE ) {
736
+ warning (_ ("ignoring overly large gitattributes file '%s'" ), path );
737
+ fclose (fp );
738
+ return NULL ;
739
+ }
725
740
726
741
CALLOC_ARRAY (res , 1 );
727
- while (fgets (buf , sizeof (buf ), fp )) {
728
- char * bufp = buf ;
729
- if (!lineno )
730
- skip_utf8_bom (& bufp , strlen (bufp ));
731
- handle_attr_line (res , bufp , path , ++ lineno , flags );
742
+ while (strbuf_getline (& buf , fp ) != EOF ) {
743
+ if (!lineno && starts_with (buf .buf , utf8_bom ))
744
+ strbuf_remove (& buf , 0 , strlen (utf8_bom ));
745
+ handle_attr_line (res , buf .buf , path , ++ lineno , flags );
732
746
}
747
+
733
748
fclose (fp );
749
+ strbuf_release (& buf );
734
750
return res ;
735
751
}
736
752
@@ -741,6 +757,7 @@ static struct attr_stack *read_attr_from_index(struct index_state *istate,
741
757
struct attr_stack * res ;
742
758
char * buf , * sp ;
743
759
int lineno = 0 ;
760
+ size_t size ;
744
761
745
762
if (!istate )
746
763
return NULL ;
@@ -759,9 +776,13 @@ static struct attr_stack *read_attr_from_index(struct index_state *istate,
759
776
if (!path_in_cone_mode_sparse_checkout (path , istate ))
760
777
return NULL ;
761
778
762
- buf = read_blob_data_from_index (istate , path , NULL );
779
+ buf = read_blob_data_from_index (istate , path , & size );
763
780
if (!buf )
764
781
return NULL ;
782
+ if (size >= ATTR_MAX_FILE_SIZE ) {
783
+ warning (_ ("ignoring overly large gitattributes blob '%s'" ), path );
784
+ return NULL ;
785
+ }
765
786
766
787
CALLOC_ARRAY (res , 1 );
767
788
for (sp = buf ; * sp ; ) {
@@ -1032,12 +1053,12 @@ static int macroexpand_one(struct all_attrs_item *all_attrs, int nr, int rem);
1032
1053
static int fill_one (const char * what , struct all_attrs_item * all_attrs ,
1033
1054
const struct match_attr * a , int rem )
1034
1055
{
1035
- int i ;
1056
+ size_t i ;
1036
1057
1037
- for (i = a -> num_attr - 1 ; rem > 0 && i >= 0 ; i -- ) {
1038
- const struct git_attr * attr = a -> state [i ].attr ;
1058
+ for (i = a -> num_attr ; rem > 0 && i > 0 ; i -- ) {
1059
+ const struct git_attr * attr = a -> state [i - 1 ].attr ;
1039
1060
const char * * n = & (all_attrs [attr -> attr_nr ].value );
1040
- const char * v = a -> state [i ].setto ;
1061
+ const char * v = a -> state [i - 1 ].setto ;
1041
1062
1042
1063
if (* n == ATTR__UNKNOWN ) {
1043
1064
debug_set (what ,
@@ -1056,11 +1077,11 @@ static int fill(const char *path, int pathlen, int basename_offset,
1056
1077
struct all_attrs_item * all_attrs , int rem )
1057
1078
{
1058
1079
for (; rem > 0 && stack ; stack = stack -> prev ) {
1059
- int i ;
1080
+ unsigned i ;
1060
1081
const char * base = stack -> origin ? stack -> origin : "" ;
1061
1082
1062
- for (i = stack -> num_matches - 1 ; 0 < rem && 0 <= i ; i -- ) {
1063
- const struct match_attr * a = stack -> attrs [i ];
1083
+ for (i = stack -> num_matches ; 0 < rem && 0 < i ; i -- ) {
1084
+ const struct match_attr * a = stack -> attrs [i - 1 ];
1064
1085
if (a -> is_macro )
1065
1086
continue ;
1066
1087
if (path_matches (path , pathlen , basename_offset ,
@@ -1091,11 +1112,11 @@ static void determine_macros(struct all_attrs_item *all_attrs,
1091
1112
const struct attr_stack * stack )
1092
1113
{
1093
1114
for (; stack ; stack = stack -> prev ) {
1094
- int i ;
1095
- for (i = stack -> num_matches - 1 ; i >= 0 ; i -- ) {
1096
- const struct match_attr * ma = stack -> attrs [i ];
1115
+ unsigned i ;
1116
+ for (i = stack -> num_matches ; i > 0 ; i -- ) {
1117
+ const struct match_attr * ma = stack -> attrs [i - 1 ];
1097
1118
if (ma -> is_macro ) {
1098
- int n = ma -> u .attr -> attr_nr ;
1119
+ unsigned int n = ma -> u .attr -> attr_nr ;
1099
1120
if (!all_attrs [n ].macro ) {
1100
1121
all_attrs [n ].macro = ma ;
1101
1122
}
@@ -1147,7 +1168,7 @@ void git_check_attr(struct index_state *istate,
1147
1168
collect_some_attrs (istate , path , check );
1148
1169
1149
1170
for (i = 0 ; i < check -> nr ; i ++ ) {
1150
- size_t n = check -> items [i ].attr -> attr_nr ;
1171
+ unsigned int n = check -> items [i ].attr -> attr_nr ;
1151
1172
const char * value = check -> all_attrs [n ].value ;
1152
1173
if (value == ATTR__UNKNOWN )
1153
1174
value = ATTR__UNSET ;
0 commit comments