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