diff options
author | Jeff Mahoney <jeffm@suse.com> | 2009-03-30 14:02:22 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-03-30 15:16:36 -0400 |
commit | cacbe3d7ad3c0a345ca1ce7bf1ecb4c5bfe54d7b (patch) | |
tree | 853abddd05fe175e7aacf9cc7868b28e1bfa6e62 | |
parent | 45b03d5e8e674eb6555b767e1c8eb40b671ff892 (diff) |
reiserfs: prepare_error_buf wrongly consumes va_arg
vsprintf will consume varargs on its own. Skipping them manually
results in garbage in the error buffer, or Oopses in the case of
pointers.
This patch removes the advancement and fixes a number of bugs where
crashes were observed as side effects of a regular error report.
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | fs/reiserfs/prints.c | 12 |
1 files changed, 3 insertions, 9 deletions
diff --git a/fs/reiserfs/prints.c b/fs/reiserfs/prints.c index 50ed4bd3ef63..b87b23717c23 100644 --- a/fs/reiserfs/prints.c +++ b/fs/reiserfs/prints.c | |||
@@ -157,19 +157,16 @@ static void sprintf_disk_child(char *buf, struct disk_child *dc) | |||
157 | dc_size(dc)); | 157 | dc_size(dc)); |
158 | } | 158 | } |
159 | 159 | ||
160 | static char *is_there_reiserfs_struct(char *fmt, int *what, int *skip) | 160 | static char *is_there_reiserfs_struct(char *fmt, int *what) |
161 | { | 161 | { |
162 | char *k = fmt; | 162 | char *k = fmt; |
163 | 163 | ||
164 | *skip = 0; | ||
165 | |||
166 | while ((k = strchr(k, '%')) != NULL) { | 164 | while ((k = strchr(k, '%')) != NULL) { |
167 | if (k[1] == 'k' || k[1] == 'K' || k[1] == 'h' || k[1] == 't' || | 165 | if (k[1] == 'k' || k[1] == 'K' || k[1] == 'h' || k[1] == 't' || |
168 | k[1] == 'z' || k[1] == 'b' || k[1] == 'y' || k[1] == 'a') { | 166 | k[1] == 'z' || k[1] == 'b' || k[1] == 'y' || k[1] == 'a') { |
169 | *what = k[1]; | 167 | *what = k[1]; |
170 | break; | 168 | break; |
171 | } | 169 | } |
172 | (*skip)++; | ||
173 | k++; | 170 | k++; |
174 | } | 171 | } |
175 | return k; | 172 | return k; |
@@ -193,18 +190,15 @@ static void prepare_error_buf(const char *fmt, va_list args) | |||
193 | char *fmt1 = fmt_buf; | 190 | char *fmt1 = fmt_buf; |
194 | char *k; | 191 | char *k; |
195 | char *p = error_buf; | 192 | char *p = error_buf; |
196 | int i, j, what, skip; | 193 | int what; |
197 | 194 | ||
198 | strcpy(fmt1, fmt); | 195 | strcpy(fmt1, fmt); |
199 | 196 | ||
200 | while ((k = is_there_reiserfs_struct(fmt1, &what, &skip)) != NULL) { | 197 | while ((k = is_there_reiserfs_struct(fmt1, &what)) != NULL) { |
201 | *k = 0; | 198 | *k = 0; |
202 | 199 | ||
203 | p += vsprintf(p, fmt1, args); | 200 | p += vsprintf(p, fmt1, args); |
204 | 201 | ||
205 | for (i = 0; i < skip; i++) | ||
206 | j = va_arg(args, int); | ||
207 | |||
208 | switch (what) { | 202 | switch (what) { |
209 | case 'k': | 203 | case 'k': |
210 | sprintf_le_key(p, va_arg(args, struct reiserfs_key *)); | 204 | sprintf_le_key(p, va_arg(args, struct reiserfs_key *)); |