Skip to content

Commit 284e3d2

Browse files
carlosmngitster
authored andcommitted
convert: track state in LF-to-CRLF filter
There may not be enough space to store CRLF in the output. If we don't fill the buffer, then the filter will keep getting called with the same short buffer and will loop forever. Instead, always store the CR and record whether there's a missing LF if so we store it in the output buffer the next time the function gets called. Reported-by: Henrik Grubbström <[email protected]> Signed-off-by: Carlos Martín Nieto <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 703f05a commit 284e3d2

File tree

1 file changed

+37
-13
lines changed

1 file changed

+37
-13
lines changed

convert.c

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -876,24 +876,39 @@ int is_null_stream_filter(struct stream_filter *filter)
876876
/*
877877
* LF-to-CRLF filter
878878
*/
879+
880+
struct lf_to_crlf_filter {
881+
struct stream_filter filter;
882+
int want_lf;
883+
};
884+
879885
static int lf_to_crlf_filter_fn(struct stream_filter *filter,
880886
const char *input, size_t *isize_p,
881887
char *output, size_t *osize_p)
882888
{
883-
size_t count;
889+
size_t count, o = 0;
890+
struct lf_to_crlf_filter *lf_to_crlf = (struct lf_to_crlf_filter *)filter;
891+
892+
/* Output a pending LF if we need to */
893+
if (lf_to_crlf->want_lf) {
894+
output[o++] = '\n';
895+
lf_to_crlf->want_lf = 0;
896+
}
884897

885898
if (!input)
886-
return 0; /* we do not keep any states */
899+
return 0; /* We've already dealt with the state */
900+
887901
count = *isize_p;
888902
if (count) {
889-
size_t i, o;
890-
for (i = o = 0; o < *osize_p && i < count; i++) {
903+
size_t i;
904+
for (i = 0; o < *osize_p && i < count; i++) {
891905
char ch = input[i];
892906
if (ch == '\n') {
893-
if (o + 1 < *osize_p)
894-
output[o++] = '\r';
895-
else
896-
break;
907+
output[o++] = '\r';
908+
if (o >= *osize_p) {
909+
lf_to_crlf->want_lf = 1;
910+
continue; /* We need to increase i */
911+
}
897912
}
898913
output[o++] = ch;
899914
}
@@ -904,15 +919,24 @@ static int lf_to_crlf_filter_fn(struct stream_filter *filter,
904919
return 0;
905920
}
906921

922+
static void lf_to_crlf_free_fn(struct stream_filter *filter)
923+
{
924+
free(filter);
925+
}
926+
907927
static struct stream_filter_vtbl lf_to_crlf_vtbl = {
908928
lf_to_crlf_filter_fn,
909-
null_free_fn,
929+
lf_to_crlf_free_fn,
910930
};
911931

912-
static struct stream_filter lf_to_crlf_filter_singleton = {
913-
&lf_to_crlf_vtbl,
914-
};
932+
static struct stream_filter *lf_to_crlf_filter(void)
933+
{
934+
struct lf_to_crlf_filter *lf_to_crlf = xmalloc(sizeof(*lf_to_crlf));
915935

936+
lf_to_crlf->filter.vtbl = &lf_to_crlf_vtbl;
937+
lf_to_crlf->want_lf = 0;
938+
return (struct stream_filter *)lf_to_crlf;
939+
}
916940

917941
/*
918942
* Cascade filter
@@ -1194,7 +1218,7 @@ struct stream_filter *get_stream_filter(const char *path, const unsigned char *s
11941218

11951219
else if (output_eol(crlf_action) == EOL_CRLF &&
11961220
!(crlf_action == CRLF_AUTO || crlf_action == CRLF_GUESS))
1197-
filter = cascade_filter(filter, &lf_to_crlf_filter_singleton);
1221+
filter = cascade_filter(filter, lf_to_crlf_filter());
11981222

11991223
return filter;
12001224
}

0 commit comments

Comments
 (0)