1 /*
2  * This file is part of ltrace.
3  * Copyright (C) 2011,2012,2013 Petr Machata, Red Hat Inc.
4  * Copyright (C) 1998,2004,2007,2008,2009 Juan Cespedes
5  * Copyright (C) 2006 Steve Fink
6  * Copyright (C) 2006 Ian Wienand
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of the
11  * License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301 USA
22  */
23 
24 #include <assert.h>
25 #include <stdint.h>
26 #include <stdlib.h>
27 #include <string.h>
28 
29 #include "printf.h"
30 #include "type.h"
31 #include "value.h"
32 #include "expr.h"
33 #include "zero.h"
34 #include "param.h"
35 #include "lens_default.h"
36 
37 struct param_enum {
38 	struct value array;
39 	int percent;
40 	size_t *future_length;
41 	char *format;
42 	char const *ptr;
43 	char const *end;
44 	size_t width;
45 };
46 
47 static struct param_enum *
param_printf_init(struct value * cb_args,size_t nargs,struct value_dict * arguments)48 param_printf_init(struct value *cb_args, size_t nargs,
49 		  struct value_dict *arguments)
50 {
51 	assert(nargs == 1);
52 
53 	struct process *proc = cb_args[0].inferior;
54 	assert(proc != NULL);
55 
56 	/* We expect a pointer to array.  */
57 	if (cb_args->type->type != ARGTYPE_POINTER
58 	    || cb_args->type->u.ptr_info.info->type != ARGTYPE_ARRAY)
59 		return NULL;
60 
61 	/* The element type should be either character (for narrow
62 	 * strings) or an integral type (for wide strings).  */
63 	struct arg_type_info *et
64 		= cb_args->type->u.ptr_info.info->u.array_info.elt_type;
65 	switch (et->type) {
66 	case ARGTYPE_CHAR:
67 	case ARGTYPE_SHORT:
68 	case ARGTYPE_USHORT:
69 	case ARGTYPE_INT:
70 	case ARGTYPE_UINT:
71 	case ARGTYPE_LONG:
72 	case ARGTYPE_ULONG:
73 		break;
74 	default:
75 		return NULL;
76 	}
77 
78 	struct param_enum *self = malloc(sizeof(*self));
79 	if (self == NULL) {
80 	fail:
81 		free(self);
82 		return NULL;
83 	}
84 	self->width = type_sizeof(proc, et);
85 	if (self->width == (size_t) -1)
86 		goto fail;
87 
88 	if (value_init_deref(&self->array, cb_args) < 0)
89 		goto fail;
90 	assert(self->array.type->type == ARGTYPE_ARRAY);
91 
92 	self->format = (char *)value_get_data(&self->array, arguments);
93 	if (self->format == NULL) {
94 		value_destroy(&self->array);
95 		goto fail;
96 	}
97 
98 	size_t size = value_size(&self->array, arguments);
99 	if (size == (size_t)-1) {
100 		value_destroy(&self->array);
101 		goto fail;
102 	}
103 
104 	self->percent = 0;
105 	self->ptr = self->format;
106 	self->end = self->format + size;
107 	self->future_length = NULL;
108 	return self;
109 }
110 
111 static void
drop_future_length(struct param_enum * self)112 drop_future_length(struct param_enum *self)
113 {
114 	if (self->future_length != NULL) {
115 		free(self->future_length);
116 		self->future_length = NULL;
117 	}
118 }
119 
120 static int
form_next_param(struct param_enum * self,enum arg_type format_type,enum arg_type elt_type,unsigned hlf,unsigned lng,char * len_buf,size_t len_buf_len,struct arg_type_info * infop)121 form_next_param(struct param_enum *self,
122 		enum arg_type format_type, enum arg_type elt_type,
123 		unsigned hlf, unsigned lng, char *len_buf, size_t len_buf_len,
124 		struct arg_type_info *infop)
125 {
126 	/* XXX note: Some types are wrong because we lack
127 	   ARGTYPE_LONGLONG, ARGTYPE_UCHAR and ARGTYPE_SCHAR.  */
128 	assert(lng <= 2);
129 	assert(hlf <= 2);
130 	static enum arg_type ints[] =
131 		{ ARGTYPE_CHAR, ARGTYPE_SHORT, ARGTYPE_INT,
132 		  ARGTYPE_LONG, ARGTYPE_ULONG };
133 	static enum arg_type uints[] =
134 		{ ARGTYPE_CHAR, ARGTYPE_USHORT, ARGTYPE_UINT,
135 		  ARGTYPE_ULONG, ARGTYPE_ULONG };
136 
137 	struct arg_type_info *elt_info = NULL;
138 	if (format_type == ARGTYPE_ARRAY || format_type == ARGTYPE_POINTER)
139 		elt_info = type_get_simple(elt_type);
140 	else if (format_type == ARGTYPE_INT)
141 		format_type = ints[2 + lng - hlf];
142 	else if (format_type == ARGTYPE_UINT)
143 		format_type = uints[2 + lng - hlf];
144 
145 
146 	if (format_type == ARGTYPE_ARRAY) {
147 		struct arg_type_info *array = malloc(sizeof(*array));
148 		if (array == NULL)
149 			return -1;
150 
151 		struct expr_node *node = NULL;
152 		int own_node;
153 		if (len_buf_len != 0
154 		    || self->future_length != NULL) {
155 			struct tmp {
156 				struct expr_node node;
157 				struct arg_type_info type;
158 			};
159 			struct tmp *len = malloc(sizeof(*len));
160 			if (len == NULL) {
161 			fail:
162 				free(len);
163 				free(array);
164 				return -1;
165 			}
166 
167 			len->type = *type_get_simple(ARGTYPE_LONG);
168 
169 			long l;
170 			if (self->future_length != NULL) {
171 				l = *self->future_length;
172 				drop_future_length(self);
173 			} else {
174 				l = atol(len_buf);
175 			}
176 
177 			expr_init_const_word(&len->node, l, &len->type, 0);
178 
179 			node = build_zero_w_arg(&len->node, 1);
180 			if (node == NULL)
181 				goto fail;
182 			own_node = 1;
183 
184 		} else {
185 			node = expr_node_zero();
186 			own_node = 0;
187 		}
188 		assert(node != NULL);
189 
190 		type_init_array(array, elt_info, 0, node, own_node);
191 		type_init_pointer(infop, array, 1);
192 
193 	} else if (format_type == ARGTYPE_POINTER) {
194 		type_init_pointer(infop, elt_info, 0);
195 
196 	} else {
197 		*infop = *type_get_simple(format_type);
198 	}
199 
200 	return 0;
201 }
202 
203 static int
param_printf_next(struct param_enum * self,struct arg_type_info * infop,int * insert_stop)204 param_printf_next(struct param_enum *self, struct arg_type_info *infop,
205 		  int *insert_stop)
206 {
207 	unsigned hlf = 0;
208 	unsigned lng = 0;
209 	enum arg_type format_type = ARGTYPE_VOID;
210 	enum arg_type elt_type = ARGTYPE_VOID;
211 	char len_buf[25] = {};
212 	size_t len_buf_len = 0;
213 	struct lens *lens = NULL;
214 
215 	for (; self->ptr < self->end; self->ptr += self->width) {
216 		union {
217 			uint8_t u8;
218 			uint16_t u16;
219 			uint32_t u32;
220 			uint64_t u64;
221 			char buf[0];
222 		} u;
223 		memcpy(u.buf, self->ptr, self->width);
224 		switch (self->width) {
225 		case 1: u.u64 = u.u8; break;
226 		case 2: u.u64 = u.u16; break;
227 		case 4: u.u64 = u.u32; break;
228 		}
229 		uint64_t c = u.u64;
230 
231 		if (!self->percent) {
232 			if (c == '%')
233 				self->percent = 1;
234 			continue;
235 		}
236 
237 		switch (c) {
238 		case '#': case ' ': case '-':
239 		case '+': case 'I': case '\'':
240 			/* These are only important for formatting,
241 			 * not for interpreting the type.  */
242 			continue;
243 
244 		case '*':
245 			/* Length parameter given in the next
246 			 * argument.  */
247 			if (self->future_length == NULL)
248 				/* This should really be an assert,
249 				 * but we can't just fail on invalid
250 				 * format string.  */
251 				self->future_length
252 					= malloc(sizeof(*self->future_length));
253 
254 			if (self->future_length != NULL) {
255 				self->ptr += self->width;
256 				format_type = ARGTYPE_INT;
257 				break;
258 			}
259 
260 		case '0':
261 		case '1': case '2': case '3':
262 		case '4': case '5': case '6':
263 		case '7': case '8': case '9':
264 			/* Field length likewise, but we need to parse
265 			 * this to attach the appropriate string
266 			 * length expression.  */
267 			if (len_buf_len < sizeof(len_buf) - 1)
268 				len_buf[len_buf_len++] = c;
269 			continue;
270 
271 		case 'h':
272 			if (hlf < 2)
273 				hlf++;
274 			continue;
275 
276 		case 'l':
277 			if (lng < 2)
278 				lng++;
279 			continue;
280 
281 		case 'q':
282 			lng = 2;
283 			continue;
284 
285 		case 'L': /* long double */
286 			lng = 1;
287 			continue;
288 
289 		case 'j': /* intmax_t */
290 			/*   XXX ABI should know */
291 			lng = 2;
292 			continue;
293 
294 		case 't': /* ptrdiff_t */
295 		case 'Z': case 'z': /* size_t */
296 			lng = 1; /* XXX ABI should tell */
297 			continue;
298 
299 		case 'd':
300 		case 'i':
301 			format_type = ARGTYPE_INT;
302 			self->percent = 0;
303 			break;
304 
305 		case 'o':
306 			lens = &octal_lens;
307 			goto uint;
308 
309 		case 'x': case 'X':
310 			lens = &hex_lens;
311 			/* Fall through.  */
312 		case 'u':
313 		uint:
314 			format_type = ARGTYPE_UINT;
315 			self->percent = 0;
316 			break;
317 
318 		case 'e': case 'E':
319 		case 'f': case 'F':
320 		case 'g': case 'G':
321 		case 'a': case 'A':
322 			format_type = ARGTYPE_DOUBLE;
323 			self->percent = 0;
324 			break;
325 
326 		case 'C': /* like "lc" */
327 			if (lng == 0)
328 				lng++;
329 		case 'c':
330 			/* XXX "lc" means wchar_t string.  */
331 			format_type = ARGTYPE_CHAR;
332 			self->percent = 0;
333 			break;
334 
335 		case 'S': /* like "ls" */
336 			if (lng == 0)
337 				lng++;
338 		case 's':
339 			format_type = ARGTYPE_ARRAY;
340 			elt_type = lng == 0 ? ARGTYPE_CHAR : ARGTYPE_INT;
341 			self->percent = 0;
342 			lens = &string_lens;
343 			break;
344 
345 		case 'p':
346 		case 'n': /* int* where to store no. of printed chars.  */
347 			format_type = ARGTYPE_POINTER;
348 			elt_type = ARGTYPE_VOID;
349 			self->percent = 0;
350 			break;
351 
352 		case 'm': /* (glibc) print argument of errno */
353 		case '%':
354 			lng = 0;
355 			hlf = 0;
356 			self->percent = 0;
357 			continue;
358 
359 		default:
360 			continue;
361 		}
362 
363 		/* If we got here, the type must have been set.  */
364 		assert(format_type != ARGTYPE_VOID);
365 
366 		if (form_next_param(self, format_type, elt_type, hlf, lng,
367 				    len_buf, len_buf_len, infop) < 0)
368 			return -1;
369 
370 		infop->lens = lens;
371 		infop->own_lens = 0;
372 
373 		return 0;
374 	}
375 
376 	*infop = *type_get_simple(ARGTYPE_VOID);
377 	return 0;
378 }
379 
380 static enum param_status
param_printf_stop(struct param_enum * self,struct value * value)381 param_printf_stop(struct param_enum *self, struct value *value)
382 {
383 	if (self->future_length != NULL
384 	    && value_extract_word(value, (long *)self->future_length, NULL) < 0)
385 		drop_future_length(self);
386 
387 	return PPCB_CONT;
388 }
389 
390 static void
param_printf_done(struct param_enum * context)391 param_printf_done(struct param_enum *context)
392 {
393 	value_destroy(&context->array);
394 	free(context);
395 }
396 
397 void
param_pack_init_printf(struct param * param,struct expr_node * arg,int own_arg)398 param_pack_init_printf(struct param *param, struct expr_node *arg, int own_arg)
399 {
400 	param_init_pack(param, PARAM_PACK_VARARGS, arg, 1, own_arg,
401 			&param_printf_init, &param_printf_next,
402 			&param_printf_stop, &param_printf_done);
403 }
404