Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 27 additions & 24 deletions bstring/bstraux.c
Original file line number Diff line number Diff line change
Expand Up @@ -989,40 +989,42 @@ bSetChar(bstring b, int pos, char c)
bstring
bSecureInput(int maxlen, int termchar, bNgetc vgetchar, void *vgcCtx)
{
size_t i, m, c;
bstring b, t;
size_t i;
size_t m;
int c;
int done;
bstring b;
bstring t;
if (!vgetchar) {
return NULL;
}
b = bfromcstralloc(INIT_SECURE_INPUT_LENGTH, "");
if (!b) {
return NULL;
}
if ((c = UCHAR_MAX + 1) == (size_t)termchar) {
c++;
}
for (i = 0; ; i++) {
if ((size_t)termchar == c ||
(maxlen > 0 && i >= (size_t)maxlen)) {
c = (size_t)EOF;
} else {
c = vgetchar (vgcCtx);
}
if ((size_t)EOF == c) {
break;
i = 0;
done = 0;
while (!done && (maxlen <= 0 || i < (size_t)maxlen)) {
c = vgetchar(vgcCtx);
if (EOF == c) {
done = 1;
continue;
}
if (i + 1 >= (size_t)b->mlen) {
/* Double size, but deal with unusual case of numeric
* overflows
*/
if ((m = b->mlen << 1) <= (size_t)b->mlen &&
(m = b->mlen + 1024) <= (size_t)b->mlen &&
(m = b->mlen + 16) <= (size_t)b->mlen &&
(m = b->mlen + 1) <= (size_t)b->mlen) {
t = NULL;
/* Double size, and deal with numeric overflows */
if (b->mlen <= INT_MAX / 2) {
m = (size_t)b->mlen << 1;
} else if (b->mlen <= INT_MAX - 1024) {
m = (size_t)b->mlen + 1024;
} else if (b->mlen <= INT_MAX - 16) {
m = (size_t)b->mlen + 16;
} else if (b->mlen <= INT_MAX - 1) {
m = (size_t)b->mlen + 1;
} else {
t = bfromcstralloc ((int)m, "");
bSecureDestroy(b); /* Cleanse partial buffer */
return NULL;
}
t = bfromcstrrangealloc(b->mlen + 1, (int)m, "");
if (t) {
memcpy(t->data, b->data, i);
}
Expand All @@ -1032,7 +1034,8 @@ bSecureInput(int maxlen, int termchar, bNgetc vgetchar, void *vgcCtx)
return b;
}
}
b->data[i] = (unsigned char)c;
b->data[i++] = (unsigned char)c;
done = (termchar == c);
}
b->slen = (int)i;
b->data[i] = (unsigned char)'\0';
Expand Down
4 changes: 3 additions & 1 deletion bstring/bstraux.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ do { \
} while (0)

/* Backward compatibilty with previous versions of Bstrlib */
#if !defined(BSTRLIB_REDUCE_NAMESPACE_POLLUTION)
#define bAssign(a, b) \
((bassign)((a), (b)))

Expand All @@ -85,7 +86,7 @@ do { \
((bcatblk)((b), (s), (len)))

#define bCatStatic(b, s) \
bCatBlk((b), ("" s ""), sizeof (s) - 1)
bcatStatic(b, s)

#define bTrunc(b, n) \
((btrunc)((b), (n)))
Expand All @@ -110,6 +111,7 @@ do { \

#define bUuDecode(b) \
(bUuDecodeEx((b), NULL))
#endif

/* Unusual functions */

Expand Down
51 changes: 37 additions & 14 deletions bstring/bstrlib.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,37 +214,60 @@ bfromcstr(const char *str)
}

bstring
bfromcstralloc(int mlen, const char *str)
bfromcstrrangealloc(int minl, int maxl, const char *str)
{
bstring b;
int i;
size_t j;

/* Bad parameters? */
if (str == NULL) {
return NULL;
}
j = strlen(str);
i = snapUpSize((int)(j + (2 - (j != 0))));
if (i <= (int) j) {
if (maxl < minl || minl < 0) {
return NULL;
}

/* Adjust lengths */
j = strlen(str);
if ((size_t)minl < (j + 1)) {
minl = (int)(j + 1);
}
if (maxl < minl) {
maxl = minl;
}
i = maxl;

b = malloc(sizeof(struct tagbstring));
if (b == NULL) {
return NULL;
}
b->slen = (int)j;
if (i < mlen) {
i = mlen;
}
b->mlen = i;
b->data = malloc(b->mlen);
if (!b->data) {
free(b);
return NULL;

while (1) {
b->data = malloc(i);
if (b->data != NULL) {
b->mlen = i;
break;
}
int k = (i >> 1) + (minl >> 1);
if (i == k || i < minl) {
free(b);
return NULL;
}
i = k;
}
memcpy(b->data, str, j + 1);

bBlockCopy(b->data, str, j + 1);
return b;
}

bstring
bfromcstralloc(int mlen, const char *str)
{
return bfromcstrrangealloc(mlen, mlen, str);
}

bstring
blk2bstr(const void *blk, int len)
{
Expand Down Expand Up @@ -1642,7 +1665,7 @@ findreplaceengine(bstring b, const bstring find, const bstring repl,
bstring auxr = (bstring) repl;
if (!b || !b->data || !find ||
!find->data || !repl || !repl->data ||
pos < 0 || find->slen <= 0 || b->mlen < 0 ||
pos < 0 || find->slen <= 0 ||
b->slen > b->mlen || b->mlen <= 0 || b->slen < 0 ||
repl->slen < 0) {
return BSTR_ERR;
Expand Down
9 changes: 9 additions & 0 deletions bstring/bstrlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,15 @@ bfromcstr(const char *str);
BSTR_PUBLIC bstring
bfromcstralloc(int mlen, const char *str);

/**
* Create a bstring which contains the contents of the '\\0' terminated
* char* buffer str. The memory buffer backing the string is at least
* minl characters in length, but an attempt is made to allocate up to
* maxl characters.
*/
BSTR_PUBLIC bstring
bfromcstrrangealloc(int minl, int maxl, const char *str);

/**
* Create a bstring whose contents are described by the contiguous buffer
* pointing to by blk with a length of len bytes.
Expand Down
4 changes: 4 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ if cc.get_id() == 'msvc'
endforeach
endif

if get_option('reduce-namespace-pollution')
add_project_arguments('-DBSTRLIB_REDUCE_NAMESPACE_POLLUTION', language: 'c')
endif

add_project_arguments(warning_flags, language: 'c')
bstring_inc = include_directories(['.', 'bstring'])
conf_data = configuration_data()
Expand Down
6 changes: 6 additions & 0 deletions meson_options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,9 @@ option(
value: true,
description: 'Build bstring library with UTF-8 support',
)
option(
'reduce-namespace-pollution',
type: 'boolean',
value: true,
description: 'Hide backward-compatibility macros in bstraux.h',
)
55 changes: 55 additions & 0 deletions tests/bstest.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,57 @@ test0_1(const char *s, int len, const char *res)
"This is a bogus but reasonably long string. " \
"Just long enough to cause some mallocing."

static void
test0_2(const char *s, int l)
{
int i_count = l * 2;
int j_count = l * 2;
int k_count = l + 1;
int is_valgrind = getenv("VALGRIND_OPTS") != NULL;

/*
* The full matrix is O(l^3) and turns into millions of allocations for
* LONG_STRING. Keep exhaustive coverage for small inputs; sample evenly
* for large inputs and valgrind runs.
*/
if (l > 32) {
i_count = 32;
j_count = 32;
k_count = 33;
}
if (is_valgrind) {
if (i_count > 12) i_count = 12;
if (j_count > 12) j_count = 12;
if (k_count > 10) k_count = 10;
}

for (int ii = 0; ii < i_count; ii++) {
int i = (i_count <= 1) ? 0 : (ii * ((l * 2) - 1)) / (i_count - 1);
for (int jj = 0; jj < j_count; jj++) {
int j = (j_count <= 1) ? 0 : (jj * ((l * 2) - 1)) / (j_count - 1);
for (int kk = 0; kk < k_count; kk++) {
int k = (k_count <= 1) ? 0 : (kk * l) / (k_count - 1);
const char *t = s ? (s + k) : NULL;
bstring b = bfromcstrrangealloc(i, j, t);
if (NULL == b) {
ck_assert(!(i < j && t != NULL));
continue;
}
if (t == NULL || b->data == NULL) {
bdestroy(b);
ck_abort();
return; /* Just a safeguard */
}
ck_assert_int_eq(b->slen, l - k);
ck_assert_int_eq(b->data[l - k], '\0');
ck_assert(b->mlen > b->slen);
ck_assert_int_eq(memcmp(t, b->data, l - k + 1), 0);
bdestroy(b);
}
}
}
}

START_TEST(core_000)
{
/* tests with NULL */
Expand All @@ -121,6 +172,10 @@ START_TEST(core_000)
test0_1(SHORT_STRING, 30, SHORT_STRING);
test0_1(LONG_STRING, 0, LONG_STRING);
test0_1(LONG_STRING, 30, LONG_STRING);
/* bfromcstrrangealloc tests */
test0_2(NULL, 2);
test0_2(EMPTY_STRING, sizeof(EMPTY_STRING) - 1);
test0_2(LONG_STRING, sizeof(LONG_STRING) - 1);
}
END_TEST

Expand Down
2 changes: 1 addition & 1 deletion tests/testaux.c
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ core13_fgetc(void *ctx)

START_TEST(core_013)
{
struct tagbstring t0 = bsStatic("Random String");
struct tagbstring t0 = bsStatic("Random String, long enough to cause to reallocing");
struct vfgetc vctx;
bstring b;
int ret = 0;
Expand Down