Esempio n. 1
0
static const char *
driver_mysql_escape_string(struct sql_db *_db, const char *string)
{
	struct mysql_db *db = (struct mysql_db *)_db;
	size_t len = strlen(string);
	char *to;

	if (_db->state == SQL_DB_STATE_DISCONNECTED) {
		/* try connecting */
		(void)sql_connect(&db->api);
	}

	if (db->mysql == NULL) {
		/* FIXME: we don't have a valid connection, so fallback
		   to using default escaping. the next query will most
		   likely fail anyway so it shouldn't matter that much
		   what we return here.. Anyway, this API needs
		   changing so that the escaping function could already
		   fail the query reliably. */
		to = t_buffer_get(len * 2 + 1);
		len = mysql_escape_string(to, string, len);
		t_buffer_alloc(len + 1);
		return to;
	}

	to = t_buffer_get(len * 2 + 1);
	len = mysql_real_escape_string(db->mysql, to, string, len);
	t_buffer_alloc(len + 1);
	return to;
}
Esempio n. 2
0
static char *
p_strarray_join_n(pool_t pool, const char *const *arr, unsigned int arr_len,
		  const char *separator)
{
	size_t alloc_len, sep_len, len, pos, needed_space;
	unsigned int i;
	char *str;

	sep_len = strlen(separator);
        alloc_len = 64;
	str = t_buffer_get(alloc_len);
	pos = 0;

	for (i = 0; i < arr_len; i++) {
		len = strlen(arr[i]);
		needed_space = pos + len + sep_len + 1;
		if (needed_space > alloc_len) {
			alloc_len = nearest_power(needed_space);
			str = t_buffer_reget(str, alloc_len);
		}

		if (pos != 0) {
			memcpy(str + pos, separator, sep_len);
			pos += sep_len;
		}

		memcpy(str + pos, arr[i], len);
		pos += len;
	}
	str[pos] = '\0';
	if (!pool->datastack_pool)
		return p_memdup(pool, str, pos + 1);
	t_buffer_alloc(pos + 1);
	return str;
}
Esempio n. 3
0
char *vstrconcat(const char *str1, va_list args, size_t *ret_len)
{
	const char *str;
        char *temp;
	size_t bufsize, i, len;

	i_assert(str1 != NULL);

	str = str1;
	bufsize = STRCONCAT_BUFSIZE;
	temp = t_buffer_get(bufsize);

	i = 0;
	do {
		len = strlen(str);

		if (i + len >= bufsize) {
			/* need more memory */
			bufsize = nearest_power(i + len + 1);
			temp = t_buffer_reget(temp, bufsize);
		}

		memcpy(temp + i, str, len); i += len;

		/* next string */
		str = va_arg(args, const char *);
	} while (str != NULL);

	i_assert(i < bufsize);

	temp[i++] = '\0';
        *ret_len = i;
        return temp;
}
Esempio n. 4
0
const char *t_strflocaltime(const char *fmt, time_t t)
{
	const struct tm *tm;
	size_t bufsize = strlen(fmt) + 32;
	char *buf = t_buffer_get(bufsize);
	size_t ret;

	tm = localtime(&t);
	while ((ret = strftime(buf, bufsize, fmt, tm)) == 0) {
		bufsize *= 2;
		i_assert(bufsize <= STRFTIME_MAX_BUFSIZE);
		buf = t_buffer_get(bufsize);
	}
	t_buffer_alloc(ret + 1);
	return buf;
}
Esempio n. 5
0
int t_get_current_dir(const char **dir_r)
{
	/* @UNSAFE */
	char *dir;
	size_t size = 128;

	dir = t_buffer_get(size);
	while (getcwd(dir, size) == NULL) {
		if (errno != ERANGE)
			return -1;
		size = nearest_power(size+1);
		dir = t_buffer_get(size);
	}
	t_buffer_alloc(strlen(dir) + 1);
	*dir_r = dir;
	return 0;
}
Esempio n. 6
0
int t_readlink(const char *path, const char **dest_r)
{
	/* @UNSAFE */
	ssize_t ret;
	char *dest;
	size_t size = 128;

	dest = t_buffer_get(size);
	while ((ret = readlink(path, dest, size)) >= (ssize_t)size) {
		size = nearest_power(size+1);
		dest = t_buffer_get(size);
	}
	if (ret < 0)
		return -1;

	dest[ret] = '\0';
	t_buffer_alloc(ret + 1);
	*dest_r = dest;
	return 0;
}
Esempio n. 7
0
char *t_noalloc_strdup_vprintf(const char *format, va_list args,
			       unsigned int *size_r)
{
#define SNPRINTF_INITIAL_EXTRA_SIZE 256
	va_list args2;
	char *tmp;
	unsigned int init_size;
	int ret;
#ifdef DEBUG
	int old_errno = errno;
#endif

	VA_COPY(args2, args);

	/* the format string is modified only if %m exists in it. it happens
	   only in error conditions, so don't try to t_push() here since it'll
	   just slow down the normal code path. */
	format = printf_format_fix_get_len(format, &init_size);
	init_size += SNPRINTF_INITIAL_EXTRA_SIZE;

	tmp = t_buffer_get(init_size);
	ret = vsnprintf(tmp, init_size, format, args);
	i_assert(ret >= 0);

	*size_r = ret + 1;
	if ((unsigned int)ret >= init_size) {
		/* didn't fit with the first guess. now we know the size,
		   so try again. */
		tmp = t_buffer_get(*size_r);
		ret = vsnprintf(tmp, *size_r, format, args2);
		i_assert((unsigned int)ret == *size_r-1);
	}
#ifdef DEBUG
	/* we rely on errno not changing. it shouldn't. */
	i_assert(errno == old_errno);
#endif
	va_end(args2);
	return tmp;
}
Esempio n. 8
0
static void test_ds_buffers(void)
{
	test_begin("data-stack buffer growth");
	T_BEGIN {
		size_t i;
		unsigned char *p;
		size_t left = t_get_bytes_available();
		while (left < 10000) {
			t_malloc_no0(left); /* force a new block */
			left = t_get_bytes_available();
		}
		left -= 64; /* make room for the sentry if DEBUG */
		p = t_buffer_get(1);
		p[0] = 1;
		for (i = 2; i <= left; i++) {
			/* grow it */
			unsigned char *p2 = t_buffer_get(i);
			test_assert_idx(p == p2, i);
			p[i-1] = i;
			test_assert_idx(p[i-2] == (unsigned char)(i-1), i);
		}
		/* now fix it permanently */
		t_buffer_alloc_last_full();
		test_assert(t_get_bytes_available() < 64 + MEM_ALIGN(1));
	} T_END;
	test_end();

	test_begin("data-stack buffer interruption");
	T_BEGIN {
		void *b = t_buffer_get(1000);
		void *a = t_malloc_no0(1);
		void *b2 = t_buffer_get(1001);
		test_assert(a == b); /* expected, not guaranteed */
		test_assert(b2 != b);
	} T_END;
	test_end();

	test_begin("data-stack buffer with reallocs");
	T_BEGIN {
		size_t bigleft = t_get_bytes_available();
		size_t i;
		for (i = 1; i < bigleft-64; i += i_rand()%32) T_BEGIN {
			unsigned char *p, *p2;
			size_t left;
			t_malloc_no0(i);
			left = t_get_bytes_available();
			/* The most useful idx for the assert is 'left' */
			test_assert_idx(left <= bigleft-i, left);
			p = t_buffer_get(left/2);
			p[0] = 'Z'; p[left/2 - 1] = 'Z';
			p2 = t_buffer_get(left + left/2);
			test_assert_idx(p != p2, left);
			test_assert_idx(p[0] == 'Z', left);
			test_assert_idx(p[left/2 -1] == 'Z', left);
		} T_END;
	} T_END;
	test_end();
}
Esempio n. 9
0
void test_mempool_alloconly(void)
{
#define SENTRY_SIZE 32
#define SENTRY_CHAR '\xDE'
#define PMALLOC_MAX_COUNT 128
	pool_t pool;
	unsigned int i, j, k;
	void *mem[PMALLOC_MAX_COUNT + 1];
	char *sentry;

	test_begin("mempool_alloconly");
	for (i = 0; i < 64; i++) {
		for (j = 1; j <= 128; j++) {
			pool = pool_alloconly_create(MEMPOOL_GROWING"test", i);
			/* make sure p_malloc() doesn't overwrite unallocated
			   data in data stack. parts of the code relies on
			   this. */
			sentry = t_buffer_get(SENTRY_SIZE);
			memset(sentry, SENTRY_CHAR, SENTRY_SIZE);

			mem[0] = p_malloc(pool, j);
			memset(mem[0], j, j);

			for (k = 1; k <= PMALLOC_MAX_COUNT; k++) {
				mem[k] = p_malloc(pool, k);
				memset(mem[k], k, k);
			}
			test_assert(mem_has_bytes(sentry, SENTRY_SIZE, SENTRY_CHAR));
			test_assert(t_buffer_get(SENTRY_SIZE) == sentry);

			test_assert(mem_has_bytes(mem[0], j, j));
			for (k = 1; k <= PMALLOC_MAX_COUNT; k++)
				test_assert(mem_has_bytes(mem[k], k, k));
			pool_unref(&pool);
		}
	}
	test_end();
}
Esempio n. 10
0
void *t_buffer_reget(void *buffer, size_t size)
{
	size_t old_size;
        void *new_buffer;

	old_size = last_buffer_size;
	if (size <= old_size)
                return buffer;

	new_buffer = t_buffer_get(size);
	if (new_buffer != buffer)
                memcpy(new_buffer, buffer, old_size);

        return new_buffer;
}
Esempio n. 11
0
void array_reverse_i(struct array *array)
{
	const unsigned int element_size = array->element_size;
	unsigned int i, count = array_count_i(array);
	size_t size;
	void *data, *tmp;

	data = buffer_get_modifiable_data(array->buffer, &size);
	tmp = t_buffer_get(array->element_size);
	for (i = 0; i+1 < count; i++, count--) {
		memcpy(tmp, PTR_OFFSET(data, i * element_size), element_size);
		memcpy(PTR_OFFSET(data, i * element_size),
		       PTR_OFFSET(data, (count-1) * element_size),
		       element_size);
		memcpy(PTR_OFFSET(data, (count-1) * element_size), tmp,
		       element_size);
	}
}
Esempio n. 12
0
static void test_ds_recurse(int depth, int number, size_t size)
{
	int i;
	char **ps;
	char tag[2] = { depth+1, '\0' };
	int try_fails = 0;
	data_stack_frame_t t_id = t_push_named("test_ds_recurse[%i]", depth);
	ps = t_buffer_get(sizeof(char *) * number);
	i_assert(ps != NULL);
	t_buffer_alloc(sizeof(char *) * number);

	for (i = 0; i < number; i++) {
		ps[i] = t_malloc_no0(size/2);
		bool re = t_try_realloc(ps[i], size);
		i_assert(ps[i] != NULL);
		if (!re) {
			try_fails++;
			ps[i] = t_malloc_no0(size);
		}
		/* drop our own canaries */
		memset(ps[i], tag[0], size);
		ps[i][size-2] = 0;
	}
	/* Do not expect a high failure rate from t_try_realloc */
	test_assert_idx(try_fails <= number / 20, depth);

	/* Now recurse... */
	if(depth>0)
		test_ds_recurse(depth-1, number, size);

	/* Test our canaries are still intact */
	for (i = 0; i < number; i++) {
		test_assert_idx(strspn(ps[i], tag) == size - 2, i);
		test_assert_idx(ps[i][size-1] == tag[0], i);
	}
	test_assert_idx(t_pop(&t_id), depth);
}
Esempio n. 13
0
enum fatal_test_state fatal_data_stack(unsigned int stage)
{
#ifdef DEBUG
#define NONEXISTENT_STACK_FRAME_ID (data_stack_frame_t)999999999
	/* If we abort, then we'll be left with a dangling t_push()
	   keep a record of our temporary stack id, so we can clean up. */
	static data_stack_frame_t t_id = NONEXISTENT_STACK_FRAME_ID;
	static unsigned char *undo_ptr = NULL;
	static unsigned char undo_data;
	static bool things_are_messed_up = FALSE;
	if (stage != 0) {
		/* Presume that we need to clean up from the prior test:
		   undo the evil write, then we will be able to t_pop cleanly,
		   and finally we can end the test stanza. */
		if (things_are_messed_up || undo_ptr == NULL)
			return FATAL_TEST_ABORT; /* abort, things are messed up with t_pop */
		*undo_ptr = undo_data;
		undo_ptr = NULL;
		/* t_pop mustn't abort, that would cause recursion */
		things_are_messed_up = TRUE;
		if (t_id != NONEXISTENT_STACK_FRAME_ID && !t_pop(&t_id))
			return FATAL_TEST_ABORT; /* abort, things are messed up with us */
		things_are_messed_up = FALSE;
		t_id = NONEXISTENT_STACK_FRAME_ID;
		test_end();
	}

	switch(stage) {
	case 0: {
		unsigned char *p;
		test_begin("fatal data-stack underrun");
		t_id = t_push_named("fatal_data_stack underrun");
		size_t left = t_get_bytes_available();
		p = t_malloc_no0(left-80); /* will fit */
		p = t_malloc_no0(100); /* won't fit, will get new block */
		int seek = 0;
		/* Seek back for the canary, don't assume endianness */
		while(seek > -60 &&
		      ((p[seek+1] != 0xDB) ||
		       ((p[seek]   != 0xBA || p[seek+2] != 0xAD) &&
			(p[seek+2] != 0xBA || p[seek]   != 0xAD))))
			seek--;
		if (seek <= -60)
			return FATAL_TEST_ABORT; /* abort, couldn't find header */
		undo_ptr = p + seek;
		undo_data = *undo_ptr;
		*undo_ptr = '*';
		/* t_malloc_no0 will panic block header corruption */
		test_expect_fatal_string("Corrupted data stack canary");
		(void)t_malloc_no0(10);
		return FATAL_TEST_FAILURE;
	}

	case 1: case 2: {
		test_begin(stage == 1 ? "fatal t_malloc_no0 overrun near" : "fatal t_malloc_no0 overrun far");
		t_id = t_push_named(stage == 1 ? "fatal t_malloc_no0 overrun first" : "fatal t_malloc_no0 overrun far");
		unsigned char *p = t_malloc_no0(10);
		undo_ptr = p + 10 + (stage == 1 ? 0 : 8*4-1); /* presumes sentry size */
		undo_data = *undo_ptr;
		*undo_ptr = '*';
		/* t_pop will now fail */
		test_expect_fatal_string("buffer overflow");
		(void)t_pop(&t_id);
		t_id = NONEXISTENT_STACK_FRAME_ID; /* We're FUBAR, mustn't pop next entry */
		return FATAL_TEST_FAILURE;
	}

	case 3: case 4: {
		test_begin(stage == 3 ? "fatal t_buffer_get overrun near" : "fatal t_buffer_get overrun far");
		t_id = t_push_named(stage == 3 ? "fatal t_buffer overrun near" : "fatal t_buffer_get overrun far");
		unsigned char *p = t_buffer_get(10);
		undo_ptr = p + 10 + (stage == 3 ? 0 : 8*4-1);
		undo_data = *undo_ptr;
		*undo_ptr = '*';
		/* t_pop will now fail */
		test_expect_fatal_string("buffer overflow");
		(void)t_pop(&t_id);
		t_id = NONEXISTENT_STACK_FRAME_ID; /* We're FUBAR, mustn't pop next entry */
		return FATAL_TEST_FAILURE;
	}

	default:
		things_are_messed_up = TRUE;
		return FATAL_TEST_FINISHED;
	}
#else
	return stage == 0 ? FATAL_TEST_FINISHED : FATAL_TEST_ABORT;
#endif
}