aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2019-01-29 20:09:35 +0200
committerSergey Poznyakoff <gray@gnu.org>2019-01-29 20:09:35 +0200
commit71c8a9513b43e30358a3c5f0448a768d908852f2 (patch)
treeca723fbefd708e691d55567f593075ac0d9ed62c
parent84800d74f3c2855fe80d1bc5060923cdb9046551 (diff)
downloadmailfromd-71c8a9513b43e30358a3c5f0448a768d908852f2.tar.gz
mailfromd-71c8a9513b43e30358a3c5f0448a768d908852f2.tar.bz2
Fixes in runtime memory management
* src/builtin/sprintf.bi: Don't use pointer to format: the latter might be reallocated during stack expansions, and the pointer would end up pointing to freed memory area. Another way to fix it would be to make env_register_auto and env_pop_auto global and to mark the address of pointer with env_register_auto so it would be reallocated together with format. However, I wouldn't like to expose too much of the internals of prog.c. * src/prog.c (env_get_locus) (heap_obstack_grow,pushs): Fix argument to env_register_auto. (env_register_auto): Check if the argument points to a memory location within data segment + stack. This is necessary, because heap_obstack_grow registers its argument, which at least in one case is a pointer to an automatic variable (see MF_OBSTACK_1GROW in builtin/snarf.m4). (env_pop_auto,env_unregister_autos) (env_fixup_autos): Make static.
-rw-r--r--src/builtin/sprintf.bi96
-rw-r--r--src/prog.c19
2 files changed, 62 insertions, 53 deletions
diff --git a/src/builtin/sprintf.bi b/src/builtin/sprintf.bi
index 11effd58..0a927dd2 100644
--- a/src/builtin/sprintf.bi
+++ b/src/builtin/sprintf.bi
@@ -34,14 +34,15 @@ typedef enum {
34 fmts_conv /* Expect conversion specifier */ 34 fmts_conv /* Expect conversion specifier */
35} printf_format_state; 35} printf_format_state;
36 36
37char * 37static int
38get_num(char *p, unsigned *pn) 38get_num(const char *p, int i, unsigned *pn)
39{ 39{
40 unsigned n = 0; 40 unsigned n = 0;
41 for (; *p && mu_isdigit(*p); p++) 41
42 n = n * 10 + *p - '0'; 42 for (; p[i] && mu_isdigit(p[i]); i++)
43 n = n * 10 + p[i] - '0';
43 *pn = n; 44 *pn = n;
44 return p; 45 return i;
45} 46}
46 47
47#define __MF_MAX(a,b) ((a)>(b) ? (a) : (b)) 48#define __MF_MAX(a,b) ((a)>(b) ? (a) : (b))
@@ -50,8 +51,8 @@ get_num(char *p, unsigned *pn)
50MF_DEFUN_VARARGS_NO_PROM(sprintf, STRING, STRING format) 51MF_DEFUN_VARARGS_NO_PROM(sprintf, STRING, STRING format)
51{ 52{
52 int i = 0; 53 int i = 0;
53 char *p = format; 54 int cur = 0;
54 char *start; 55 int start;
55 char buf[SPRINTF_BUF_SIZE]; 56 char buf[SPRINTF_BUF_SIZE];
56 printf_format_state state = fmts_copy; 57 printf_format_state state = fmts_copy;
57 int flags = 0; 58 int flags = 0;
@@ -61,7 +62,7 @@ MF_DEFUN_VARARGS_NO_PROM(sprintf, STRING, STRING format)
61 62
62 MF_OBSTACK_BEGIN(); 63 MF_OBSTACK_BEGIN();
63 MF_VA_START(); 64 MF_VA_START();
64 while (*p) { 65 while (format[cur]) {
65 unsigned n; 66 unsigned n;
66 char *str; 67 char *str;
67 long num; 68 long num;
@@ -71,31 +72,31 @@ MF_DEFUN_VARARGS_NO_PROM(sprintf, STRING, STRING format)
71 switch (state) { 72 switch (state) {
72 case fmts_copy: 73 case fmts_copy:
73 /* Expect `%', and copy all the rest verbatim */ 74 /* Expect `%', and copy all the rest verbatim */
74 if (*p == '%') { 75 if (format[cur] == '%') {
75 start = p; 76 start = cur;
76 state = fmts_pos; 77 state = fmts_pos;
77 flags = 0; 78 flags = 0;
78 width = 0; 79 width = 0;
79 prec = 0; 80 prec = 0;
80 } else 81 } else
81 MF_OBSTACK_1GROW(*p); 82 MF_OBSTACK_1GROW(format[cur]);
82 p++; 83 cur++;
83 break; 84 break;
84 85
85 case fmts_pos: 86 case fmts_pos:
86 /* Expect '%' or an argument position -- %_% or %_2$ */ 87 /* Expect '%' or an argument position -- %_% or %_2$ */
87 if (*p == '%') { 88 if (format[cur] == '%') {
88 MF_OBSTACK_1GROW('%'); 89 MF_OBSTACK_1GROW('%');
89 p++; 90 cur++;
90 state = fmts_copy; 91 state = fmts_copy;
91 break; 92 break;
92 } 93 }
93 if (mu_isdigit(*p)) { 94 if (mu_isdigit(format[cur])) {
94 char *q = get_num(p, &n); 95 int pos = get_num(format, cur, &n);
95 if (*q == '$') { 96 if (format[pos] == '$') {
96 argnum = n - 1; 97 argnum = n - 1;
97 flags |= FMT_ALTPOS; 98 flags |= FMT_ALTPOS;
98 p = q + 1; 99 cur = pos + 1;
99 } 100 }
100 } 101 }
101 state = fmts_flags; 102 state = fmts_flags;
@@ -103,30 +104,30 @@ MF_DEFUN_VARARGS_NO_PROM(sprintf, STRING, STRING format)
103 104
104 case fmts_flags: 105 case fmts_flags:
105 /* Expect flags -- %2$_# */ 106 /* Expect flags -- %2$_# */
106 switch (*p) { 107 switch (format[cur]) {
107 case '#': 108 case '#':
108 flags |= FMT_ALTERNATE; 109 flags |= FMT_ALTERNATE;
109 p++; 110 cur++;
110 break; 111 break;
111 112
112 case '0': 113 case '0':
113 flags |= FMT_PADZERO; 114 flags |= FMT_PADZERO;
114 p++; 115 cur++;
115 break; 116 break;
116 117
117 case '-': 118 case '-':
118 flags |= FMT_ADJUST_LEFT; 119 flags |= FMT_ADJUST_LEFT;
119 p++; 120 cur++;
120 break; 121 break;
121 122
122 case ' ': 123 case ' ':
123 flags |= FMT_SPACEPFX; 124 flags |= FMT_SPACEPFX;
124 p++; 125 cur++;
125 break; 126 break;
126 127
127 case '+': 128 case '+':
128 flags |= FMT_SIGNPFX; 129 flags |= FMT_SIGNPFX;
129 p++; 130 cur++;
130 break; 131 break;
131 132
132 default: 133 default:
@@ -136,11 +137,11 @@ MF_DEFUN_VARARGS_NO_PROM(sprintf, STRING, STRING format)
136 137
137 case fmts_width: 138 case fmts_width:
138 /* Expect width -- %2$#_8 or %2$#_* */ 139 /* Expect width -- %2$#_8 or %2$#_* */
139 if (mu_isdigit(*p)) { 140 if (mu_isdigit(format[cur])) {
140 p = get_num(p, &width); 141 cur = get_num(format, cur, &width);
141 state = fmts_prec; 142 state = fmts_prec;
142 } else if (*p == '*') { 143 } else if (format[cur] == '*') {
143 p++; 144 cur++;
144 state = fmts_width_arg; 145 state = fmts_width_arg;
145 } else 146 } else
146 state = fmts_prec; 147 state = fmts_prec;
@@ -149,11 +150,11 @@ MF_DEFUN_VARARGS_NO_PROM(sprintf, STRING, STRING format)
149 case fmts_width_arg: 150 case fmts_width_arg:
150 /* Expect width argument position -- %2$#*_1$ */ 151 /* Expect width argument position -- %2$#*_1$ */
151 state = fmts_prec; 152 state = fmts_prec;
152 if (mu_isdigit(*p)) { 153 if (mu_isdigit(format[cur])) {
153 char *q = get_num(p, &n); 154 int pos = get_num(format, cur, &n);
154 if (*q == '$') { 155 if (format[pos] == '$') {
155 MF_VA_ARG(n-1, NUMBER, num); 156 MF_VA_ARG(n-1, NUMBER, num);
156 p = q + 1; 157 cur = pos + 1;
157 if (num < 0) { 158 if (num < 0) {
158 flags |= FMT_SPACEPFX; 159 flags |= FMT_SPACEPFX;
159 num = - num; 160 num = - num;
@@ -176,12 +177,12 @@ MF_DEFUN_VARARGS_NO_PROM(sprintf, STRING, STRING format)
176 case fmts_prec: 177 case fmts_prec:
177 /* Expect precision -- %2$#*1$_. */ 178 /* Expect precision -- %2$#*1$_. */
178 state = fmts_conv; 179 state = fmts_conv;
179 if (*p == '.') { 180 if (format[cur] == '.') {
180 p++; 181 cur++;
181 if (mu_isdigit(*p)) { 182 if (mu_isdigit(format[cur])) {
182 p = get_num(p, &prec); 183 cur = get_num(format, cur, &prec);
183 } else if (*p == '*') { 184 } else if (format[cur] == '*') {
184 p++; 185 cur++;
185 state = fmts_prec_arg; 186 state = fmts_prec_arg;
186 } 187 }
187 } 188 }
@@ -191,13 +192,13 @@ MF_DEFUN_VARARGS_NO_PROM(sprintf, STRING, STRING format)
191 /* Expect precision argument position -- 192 /* Expect precision argument position --
192