diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2019-01-29 20:09:35 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2019-01-29 20:09:35 +0200 |
commit | 71c8a9513b43e30358a3c5f0448a768d908852f2 (patch) | |
tree | ca723fbefd708e691d55567f593075ac0d9ed62c | |
parent | 84800d74f3c2855fe80d1bc5060923cdb9046551 (diff) | |
download | mailfromd-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.bi | 96 | ||||
-rw-r--r-- | src/prog.c | 19 |
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 | ||
37 | char * | 37 | static int |
38 | get_num(char *p, unsigned *pn) | 38 | get_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) | |||
50 | MF_DEFUN_VARARGS_NO_PROM(sprintf, STRING, STRING format) | 51 | MF_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 |