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
37struct 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
47static struct param_enum *
48param_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
111static void
112drop_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
120static int
121form_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
203static int
204param_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
380static enum param_status
381param_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
390static void
391param_printf_done(struct param_enum *context)
392{
393	value_destroy(&context->array);
394	free(context);
395}
396
397void
398param_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