buffer.c revision e915ba86f157549b7d127f92312bc487b249df7e
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2002-2015 Dovecot authors, see the included COPYING file */
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen/* @UNSAFE: whole file */
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen /* public: */
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen const unsigned char *r_buffer;
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen /* private: */
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen unsigned char *w_buffer;
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainentypedef int buffer_check_sizes[COMPILE_ERROR_IF_TRUE(sizeof(struct real_buffer) > sizeof(buffer_t)) ?1:1];
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainenstatic void buffer_alloc(struct real_buffer *buf, size_t size)
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen i_assert(buf->w_buffer == NULL || buf->alloced);
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen buf->w_buffer = p_realloc(buf->pool, buf->w_buffer, buf->alloc, size);
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainenstatic inline void
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainenbuffer_check_limits(struct real_buffer *buf, size_t pos, size_t data_size)
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen unsigned int extra;
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen i_panic("Buffer write out of range (%"PRIuSIZE_T
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen if (new_size > buf->used && buf->used < buf->dirty) {
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen /* clear used..dirty area */
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen size_t max = I_MIN(I_MIN(buf->alloc, buf->dirty), new_size);
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen memset(buf->w_buffer + buf->used, 0, max - buf->used);
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen /* always keep +1 byte allocated available in case str_c() is called
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen for this buffer. this is mainly for cases where the buffer is
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen allocated from data stack, and str_c() is called in a separate stack
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen i_panic("Buffer full (%"PRIuSIZE_T" > %"PRIuSIZE_T", "
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen buffer_alloc(buf, pool_get_exp_grown_size(buf->pool, buf->alloc,
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen else if (new_size > buf->used && buf->alloced &&
8ccb1a013b07e7ca37b7281732b78c042f128388Timo Sirainen !buf->pool->alloconly_pool && !buf->pool->datastack_pool) {
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen /* buffer's size increased: move the buffer's memory elsewhere.
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen this should help catch bugs where old pointers are tried to
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen be used to access the buffer's memory */
2c7cde7c78ccb28dcaa864d262ed6e991a7e8eb7Timo Sirainenvoid buffer_create_from_data(buffer_t *buffer, void *data, size_t size)
8ccb1a013b07e7ca37b7281732b78c042f128388Timo Sirainen i_assert(sizeof(*buffer) >= sizeof(struct real_buffer));
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen /* clear the whole memory area. unnecessary usually, but if the
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen buffer is used by e.g. str_c() it tries to access uninitialized
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainenvoid buffer_create_from_const_data(buffer_t *buffer,
8ccb1a013b07e7ca37b7281732b78c042f128388Timo Sirainen i_assert(sizeof(*buffer) >= sizeof(struct real_buffer));
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainenbuffer_t *buffer_create_dynamic(pool_t pool, size_t init_size)
c6ce2e251ac75fa650c7fbfa52150eae69386293Martti Rannanjärvi buf = p_new(pool, struct real_buffer, 1);
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen struct real_buffer *buf = (struct real_buffer *)*_buf;
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainenvoid *buffer_free_without_data(buffer_t **_buf)
8ccb1a013b07e7ca37b7281732b78c042f128388Timo Sirainen struct real_buffer *buf = (struct real_buffer *)*_buf;
8ccb1a013b07e7ca37b7281732b78c042f128388Timo Sirainen const struct real_buffer *buf = (const struct real_buffer *)_buf;
132bfe8fcb7a1be790dc8b5bf9d155c9f060808dTimo Sirainen struct real_buffer *buf = (struct real_buffer *)_buf;
95c4f06cba717df14358ec883b1bd1aec6cbf0a1Timo Sirainenvoid buffer_append(buffer_t *buf, const void *data, size_t data_size)
95c4f06cba717df14358ec883b1bd1aec6cbf0a1Timo Sirainen buffer_write(buf, buf->used, data, data_size);
95c4f06cba717df14358ec883b1bd1aec6cbf0a1Timo Sirainenvoid buffer_append_c(buffer_t *buf, unsigned char chr)
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen struct real_buffer *buf = (struct real_buffer *)_buf;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen buffer_copy(_buf, pos + data_size, _buf, pos, (size_t)-1);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainenvoid buffer_delete(buffer_t *_buf, size_t pos, size_t size)
71e88fae3be360e9a93b3398e743f99a6f05d2edTimo Sirainen struct real_buffer *buf = (struct real_buffer *)_buf;
206ac4273fa102500fa017f0c21a4fd72e94665aTimo Sirainen /* delete from between */
95c4f06cba717df14358ec883b1bd1aec6cbf0a1Timo Sirainen /* delete the rest of the buffer */
95c4f06cba717df14358ec883b1bd1aec6cbf0a1Timo Sirainenvoid buffer_write_zero(buffer_t *_buf, size_t pos, size_t data_size)
95c4f06cba717df14358ec883b1bd1aec6cbf0a1Timo Sirainen struct real_buffer *buf = (struct real_buffer *)_buf;
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainenvoid buffer_append_zero(buffer_t *buf, size_t data_size)
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainenvoid buffer_insert_zero(buffer_t *_buf, size_t pos, size_t data_size)
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen struct real_buffer *buf = (struct real_buffer *)_buf;
f318b3dbe2acc177b8ee1c160e4b5b14e7f2cd41Timo Sirainen buffer_copy(_buf, pos + data_size, _buf, pos, (size_t)-1);
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainenvoid buffer_copy(buffer_t *_dest, size_t dest_pos,
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen const buffer_t *_src, size_t src_pos, size_t copy_size)
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen struct real_buffer *dest = (struct real_buffer *)_dest;
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen const struct real_buffer *src = (const struct real_buffer *)_src;
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen buffer_check_limits(dest, dest_pos, copy_size);
return FALSE;
void *ret;