aboutsummaryrefslogtreecommitdiffstats
path: root/main/busybox/0001-sed-prevent-overflow-of-length-from-bb_get_chunk_fro.patch
blob: da0121cadc0907719c948ff1e42bcbaf284e067c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
From e2afae6303e871a31a061d03359cfcd5dd86c088 Mon Sep 17 00:00:00 2001
From: Quentin Rameau <quinq@fifth.space>
Date: Sun, 1 Apr 2018 19:49:58 +0200
Subject: [PATCH] sed: prevent overflow of length from bb_get_chunk_from_file

This fragment did not work right:

                temp = bb_get_chunk_from_file(fp, &len);
                if (temp) {
                        /* len > 0 here, it's ok to do temp[len-1] */
                        char c = temp[len-1];

With "int len" _sign-extending_, temp[len-1] can refer to a wrong location
if len > 0x7fffffff.

Signed-off-by: Quentin Rameau <quinq@fifth.space>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 editors/sed.c              |  2 +-
 include/libbb.h            |  2 +-
 libbb/get_line_from_file.c | 11 +++++++----
 3 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/editors/sed.c b/editors/sed.c
index 9d800c2c3..470220859 100644
--- a/editors/sed.c
+++ b/editors/sed.c
@@ -988,7 +988,7 @@ static void flush_append(char *last_puts_char)
 static char *get_next_line(char *gets_char, char *last_puts_char)
 {
 	char *temp = NULL;
-	int len;
+	size_t len;
 	char gc;
 
 	flush_append(last_puts_char);
diff --git a/include/libbb.h b/include/libbb.h
index fa878433e..309c58734 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -911,7 +911,7 @@ extern void xprint_and_close_file(FILE *file) FAST_FUNC;
  * end of line. If end isn't NULL, length of the chunk is stored in it.
  * Returns NULL if EOF/error.
  */
-extern char *bb_get_chunk_from_file(FILE *file, int *end) FAST_FUNC;
+extern char *bb_get_chunk_from_file(FILE *file, size_t *end) FAST_FUNC;
 /* Reads up to (and including) TERMINATING_STRING: */
 extern char *xmalloc_fgets_str(FILE *file, const char *terminating_string) FAST_FUNC RETURNS_MALLOC;
 /* Same, with limited max size, and returns the length (excluding NUL): */
diff --git a/libbb/get_line_from_file.c b/libbb/get_line_from_file.c
index 941ea12b5..d10066937 100644
--- a/libbb/get_line_from_file.c
+++ b/libbb/get_line_from_file.c
@@ -10,16 +10,19 @@
  */
 #include "libbb.h"
 
-char* FAST_FUNC bb_get_chunk_from_file(FILE *file, int *end)
+char* FAST_FUNC bb_get_chunk_from_file(FILE *file, size_t *end)
 {
 	int ch;
-	unsigned idx = 0;
+	size_t idx = 0;
 	char *linebuf = NULL;
 
 	while ((ch = getc(file)) != EOF) {
 		/* grow the line buffer as necessary */
-		if (!(idx & 0xff))
+		if (!(idx & 0xff)) {
+			if (idx == ((size_t)-1) - 0xff)
+				bb_error_msg_and_die(bb_msg_memory_exhausted);
 			linebuf = xrealloc(linebuf, idx + 0x100);
+		}
 		linebuf[idx++] = (char) ch;
 		if (ch == '\0')
 			break;
@@ -49,7 +52,7 @@ char* FAST_FUNC xmalloc_fgets(FILE *file)
 /* Get line.  Remove trailing \n */
 char* FAST_FUNC xmalloc_fgetline(FILE *file)
 {
-	int i;
+	size_t i;
 	char *c = bb_get_chunk_from_file(file, &i);
 
 	if (i && c[--i] == '\n')
-- 
2.16.3