general: Fix memory Corruption in __ast_string_field_ptr_build_va.

If the space left in a stringfield is between 0 and
(alignof(ast_string_field_allocation)-1) adding new data would cause
memory corruption, because we would assume enough space (unsigned
underrun).

Thanks Arnd Schmitter for reporting and finding out the cause!

ASTERISK-23508 #close
Reported by: Arnd Schmitter
Tested by: Arnd Schmitter, JoshE

Review: https://reviewboard.asterisk.org/r/3898/
........

Merged revisions 420680 from http://svn.asterisk.org/svn/asterisk/branches/1.8


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/11@420715 65c4cc65-6c06-0410-ace0-fbb531ad65f3
changes/61/61/1
Walter Doekes 11 years ago
parent d43da8846c
commit 9aba91e5a6

@ -1960,6 +1960,7 @@ void __ast_string_field_ptr_build_va(struct ast_string_field_mgr *mgr,
size_t needed; size_t needed;
size_t available; size_t available;
size_t space = (*pool_head)->size - (*pool_head)->used; size_t space = (*pool_head)->size - (*pool_head)->used;
int res;
ssize_t grow; ssize_t grow;
char *target; char *target;
va_list ap2; va_list ap2;
@ -1979,13 +1980,23 @@ void __ast_string_field_ptr_build_va(struct ast_string_field_mgr *mgr,
* so we don't need to re-align anything here. * so we don't need to re-align anything here.
*/ */
target = (*pool_head)->base + (*pool_head)->used + ast_alignof(ast_string_field_allocation); target = (*pool_head)->base + (*pool_head)->used + ast_alignof(ast_string_field_allocation);
if (space > ast_alignof(ast_string_field_allocation)) {
available = space - ast_alignof(ast_string_field_allocation); available = space - ast_alignof(ast_string_field_allocation);
} else {
available = 0;
}
} }
va_copy(ap2, ap); va_copy(ap2, ap);
needed = vsnprintf(target, available, format, ap2) + 1; res = vsnprintf(target, available, format, ap2);
va_end(ap2); va_end(ap2);
if (res < 0) {
/* Are we out of memory? */
return;
}
needed = (size_t)res + 1; /* NUL byte */
if (needed > available) { if (needed > available) {
/* the allocation could not be satisfied using the field's current allocation /* the allocation could not be satisfied using the field's current allocation
(if it has one), or the space available in the pool (if it does not). allocate (if it has one), or the space available in the pool (if it does not). allocate
@ -2004,7 +2015,8 @@ void __ast_string_field_ptr_build_va(struct ast_string_field_mgr *mgr,
*/ */
__ast_string_field_release_active(*pool_head, *ptr); __ast_string_field_release_active(*pool_head, *ptr);
mgr->last_alloc = *ptr = target; mgr->last_alloc = *ptr = target;
AST_STRING_FIELD_ALLOCATION(target) = needed; ast_assert(needed < (ast_string_field_allocation)-1);
AST_STRING_FIELD_ALLOCATION(target) = (ast_string_field_allocation)needed;
(*pool_head)->used += ast_make_room_for(needed, ast_string_field_allocation); (*pool_head)->used += ast_make_room_for(needed, ast_string_field_allocation);
(*pool_head)->active += needed; (*pool_head)->active += needed;
} else if ((grow = (needed - AST_STRING_FIELD_ALLOCATION(*ptr))) > 0) { } else if ((grow = (needed - AST_STRING_FIELD_ALLOCATION(*ptr))) > 0) {

Loading…
Cancel
Save