PR/49683: Amir Plivatsky: Off-by-one comparison in ct_decode_string() leading

to out of bounds referrence.
XXX: pullup-7
This commit is contained in:
christos 2015-02-22 00:46:58 +00:00
parent 88c9fb0be8
commit aecf67a262
2 changed files with 26 additions and 29 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: chartype.c,v 1.10 2011/08/16 16:25:15 christos Exp $ */
/* $NetBSD: chartype.c,v 1.11 2015/02/22 00:46:58 christos Exp $ */
/*-
* Copyright (c) 2009 The NetBSD Foundation, Inc.
@ -38,7 +38,7 @@
*/
#include "config.h"
#if !defined(lint) && !defined(SCCSID)
__RCSID("$NetBSD: chartype.c,v 1.10 2011/08/16 16:25:15 christos Exp $");
__RCSID("$NetBSD: chartype.c,v 1.11 2015/02/22 00:46:58 christos Exp $");
#endif /* not lint && not SCCSID */
#include "el.h"
#include <stdlib.h>
@ -46,7 +46,7 @@ __RCSID("$NetBSD: chartype.c,v 1.10 2011/08/16 16:25:15 christos Exp $");
#define CT_BUFSIZ ((size_t)1024)
#ifdef WIDECHAR
protected void
protected int
ct_conv_buff_resize(ct_buffer_t *conv, size_t mincsize, size_t minwsize)
{
void *p;
@ -57,6 +57,7 @@ ct_conv_buff_resize(ct_buffer_t *conv, size_t mincsize, size_t minwsize)
conv->csize = 0;
el_free(conv->cbuff);
conv->cbuff = NULL;
return -1;
} else
conv->cbuff = p;
}
@ -68,9 +69,11 @@ ct_conv_buff_resize(ct_buffer_t *conv, size_t mincsize, size_t minwsize)
conv->wsize = 0;
el_free(conv->wbuff);
conv->wbuff = NULL;
return -1;
} else
conv->wbuff = p;
}
return 0;
}
@ -78,26 +81,22 @@ public char *
ct_encode_string(const Char *s, ct_buffer_t *conv)
{
char *dst;
ssize_t used = 0;
ssize_t used;
if (!s)
return NULL;
if (!conv->cbuff)
ct_conv_buff_resize(conv, CT_BUFSIZ, (size_t)0);
if (!conv->cbuff)
return NULL;
dst = conv->cbuff;
while (*s) {
used = (ssize_t)(conv->csize - (size_t)(dst - conv->cbuff));
if (used < 5) {
used = dst - conv->cbuff;
ct_conv_buff_resize(conv, conv->csize + CT_BUFSIZ,
(size_t)0);
if (!conv->cbuff)
for (;;) {
used = (ssize_t)(dst - conv->cbuff);
if ((conv->csize - (size_t)used) < 5) {
if (ct_conv_buff_resize(conv, conv->csize + CT_BUFSIZ,
(size_t)0) == -1)
return NULL;
dst = conv->cbuff + used;
}
if (!*s)
break;
used = ct_encode_char(dst, (size_t)5, *s);
if (used == -1) /* failed to encode, need more buffer space */
abort();
@ -111,22 +110,19 @@ ct_encode_string(const Char *s, ct_buffer_t *conv)
public Char *
ct_decode_string(const char *s, ct_buffer_t *conv)
{
size_t len = 0;
size_t len;
if (!s)
return NULL;
if (!conv->wbuff)
ct_conv_buff_resize(conv, (size_t)0, CT_BUFSIZ);
if (!conv->wbuff)
return NULL;
len = ct_mbstowcs(NULL, s, (size_t)0);
if (len == (size_t)-1)
return NULL;
if (len > conv->wsize)
ct_conv_buff_resize(conv, (size_t)0, len + 1);
if (!conv->wbuff)
return NULL;
if (conv->csize < ++len)
if (ct_conv_buff_resize(conv, (size_t)0, len + CT_BUFSIZ) == -1)
return NULL;
ct_mbstowcs(conv->wbuff, s, conv->wsize);
return conv->wbuff;
}
@ -145,9 +141,10 @@ ct_decode_argv(int argc, const char *argv[], ct_buffer_t *conv)
* the argv strings. */
for (i = 0, bufspace = 0; i < argc; ++i)
bufspace += argv[i] ? strlen(argv[i]) + 1 : 0;
ct_conv_buff_resize(conv, (size_t)0, bufspace);
if (!conv->wsize)
return NULL;
if (conv->csize < ++bufspace)
if (ct_conv_buff_resize(conv, (size_t)0, bufspace + CT_BUFSIZ)
== -1)
return NULL;
wargv = el_malloc((size_t)argc * sizeof(*wargv));

View File

@ -1,4 +1,4 @@
/* $NetBSD: chartype.h,v 1.11 2015/02/17 22:49:26 christos Exp $ */
/* $NetBSD: chartype.h,v 1.12 2015/02/22 00:46:58 christos Exp $ */
/*-
* Copyright (c) 2009 The NetBSD Foundation, Inc.
@ -189,7 +189,7 @@ public Char *ct_decode_string(const char *, ct_buffer_t *);
protected Char **ct_decode_argv(int, const char *[], ct_buffer_t *);
/* Resizes the conversion buffer(s) if needed. */
protected void ct_conv_buff_resize(ct_buffer_t *, size_t, size_t);
protected int ct_conv_buff_resize(ct_buffer_t *, size_t, size_t);
protected ssize_t ct_encode_char(char *, size_t, Char);
protected size_t ct_enc_width(Char);