Page MenuHomeFreeBSD

D57355.id178973.diff
No OneTemporary

D57355.id178973.diff

diff --git a/lib/libc/stdio/open_memstream.c b/lib/libc/stdio/open_memstream.c
--- a/lib/libc/stdio/open_memstream.c
+++ b/lib/libc/stdio/open_memstream.c
@@ -28,9 +28,11 @@
*/
#include "namespace.h"
+#include <sys/param.h>
#include <assert.h>
#include <errno.h>
#include <limits.h>
+#include <stdbool.h>
#ifdef DEBUG
#include <stdint.h>
#endif
@@ -62,7 +64,19 @@
else
newsize = newoff;
if (newsize > ms->size) {
- buf = realloc(*ms->bufp, newsize + 1);
+ size_t growsize;
+
+ if (__builtin_mul_overflow(ms->size, 15, &growsize) ||
+ growsize / 10 >= SSIZE_MAX) {
+ growsize = SSIZE_MAX - 1;
+ } else {
+ growsize /= 10;
+ }
+
+ /* Leave newsize untouched for the later ms->len update. */
+ growsize = MAX(growsize, newsize);
+
+ buf = realloc(*ms->bufp, growsize + 1);
if (buf == NULL)
return (0);
@@ -70,9 +84,9 @@
fprintf(stderr, "MS: %p growing from %zd to %zd\n",
ms, ms->size, newsize);
#endif
- memset(buf + ms->size + 1, 0, newsize - ms->size);
+ memset(buf + ms->size + 1, 0, growsize - ms->size);
*ms->bufp = buf;
- ms->size = newsize;
+ ms->size = growsize;
}
if (newsize > ms->len)
diff --git a/lib/libc/stdio/open_wmemstream.c b/lib/libc/stdio/open_wmemstream.c
--- a/lib/libc/stdio/open_wmemstream.c
+++ b/lib/libc/stdio/open_wmemstream.c
@@ -28,9 +28,11 @@
*/
#include "namespace.h"
+#include <sys/param.h>
#include <assert.h>
#include <errno.h>
#include <limits.h>
+#include <stdbool.h>
#ifdef DEBUG
#include <stdint.h>
#endif
@@ -63,17 +65,30 @@
else
newsize = newoff;
if (newsize > ms->size) {
- buf = reallocarray(*ms->bufp, newsize + 1, sizeof(wchar_t));
+ size_t growsize;
+
+ if (__builtin_mul_overflow(ms->size, 15, &growsize) ||
+ growsize / 10 >= SSIZE_MAX) {
+ growsize = SSIZE_MAX - 1;
+ } else {
+ growsize /= 10;
+ }
+
+ /* Leave newsize untouched for the later ms->len update. */
+ growsize = MAX(growsize, newsize);
+
+ buf = reallocarray(*ms->bufp, growsize + 1, sizeof(wchar_t));
if (buf == NULL)
return (0);
#ifdef DEBUG
fprintf(stderr, "WMS: %p growing from %zd to %zd\n",
ms, ms->size, newsize);
#endif
- wmemset(buf + ms->size + 1, 0, newsize - ms->size);
+ wmemset(buf + ms->size + 1, 0, growsize - ms->size);
*ms->bufp = buf;
- ms->size = newsize;
+ ms->size = growsize;
}
+
if (newsize > ms->len)
ms->len = newsize;
return (1);
diff --git a/lib/libc/tests/stdio/open_memstream2_test.c b/lib/libc/tests/stdio/open_memstream2_test.c
--- a/lib/libc/tests/stdio/open_memstream2_test.c
+++ b/lib/libc/tests/stdio/open_memstream2_test.c
@@ -184,7 +184,40 @@
SEEK_OK(-1, SEEK_END, 2);
SEEK_OK(OFF_MAX - 1, SEEK_SET, OFF_MAX - 1);
SEEK_FAIL(2, SEEK_CUR, EOVERFLOW);
+
+ fclose(fp);
+}
+
+ATF_TC_WITHOUT_HEAD(resize_test);
+ATF_TC_BODY(resize_test, tc)
+{
+ FILE *fp;
+ size_t wsz;
+ char addition[] = "Test String";
+
+ fp = open_memstream(&buf, &len);
+ ATF_REQUIRE_MSG(fp != NULL, "open_memstream failed: %d", errno);
+
+ /* Doesn't matter what we write, we'll just want to trigger alloc 2x. */
+ wsz = fprintf(fp, "%s", addition);
+ ATF_REQUIRE_EQ(wsz, sizeof(addition) - 1);
+ ATF_REQUIRE(fflush(fp) == 0);
+
+ /* Trigger growth. */
+ ATF_REQUIRE_EQ('a', fputc('a', fp));
+ ATF_REQUIRE_EQ(wsz + 1, ftello(fp));
+
+ /*
+ * Seeking to the end shouldn't put us past the last write, because
+ * we've only done a small series of writes.
+ */
+ ATF_REQUIRE(fseek(fp, 0, SEEK_END) == 0);
+ ATF_REQUIRE_EQ(wsz + 1, ftello(fp));
+
+ ATF_REQUIRE(!ferror(fp));
fclose(fp);
+
+ ATF_REQUIRE_EQ(wsz + 1, len);
}
ATF_TP_ADD_TCS(tp)
@@ -193,6 +226,7 @@
ATF_TP_ADD_TC(tp, open_group_test);
ATF_TP_ADD_TC(tp, simple_tests);
ATF_TP_ADD_TC(tp, seek_tests);
+ ATF_TP_ADD_TC(tp, resize_test);
return (atf_no_error());
}
diff --git a/lib/libc/tests/stdio/open_wmemstream_test.c b/lib/libc/tests/stdio/open_wmemstream_test.c
--- a/lib/libc/tests/stdio/open_wmemstream_test.c
+++ b/lib/libc/tests/stdio/open_wmemstream_test.c
@@ -187,12 +187,45 @@
fclose(fp);
}
+ATF_TC_WITHOUT_HEAD(resize_test);
+ATF_TC_BODY(resize_test, tc)
+{
+ FILE *fp;
+ size_t wsz;
+ wchar_t addition[] = L"Test String";
+
+ fp = open_wmemstream(&buf, &len);
+ ATF_REQUIRE_MSG(fp != NULL, "open_memstream failed: %d", errno);
+
+ /* Doesn't matter what we write, we'll just want to trigger alloc 2x. */
+ wsz = fwprintf(fp, L"%ls", addition);
+ ATF_REQUIRE_EQ(wsz, wcslen(addition));
+ ATF_REQUIRE(fflush(fp) == 0);
+
+ /* Trigger growth. */
+ ATF_REQUIRE_EQ(L'a', fputwc(L'a', fp));
+ ATF_REQUIRE_EQ(wsz + 1, ftello(fp));
+
+ /*
+ * Seeking to the end shouldn't put us past the last write, because
+ * we've only done a small series of writes.
+ */
+ ATF_REQUIRE(fseek(fp, 0, SEEK_END) == 0);
+ ATF_REQUIRE_EQ(wsz + 1, ftello(fp));
+
+ ATF_REQUIRE(!ferror(fp));
+ fclose(fp);
+
+ ATF_REQUIRE_EQ(wsz + 1, len);
+}
+
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, open_group_test);
ATF_TP_ADD_TC(tp, simple_tests);
ATF_TP_ADD_TC(tp, seek_tests);
+ ATF_TP_ADD_TC(tp, resize_test);
return (atf_no_error());
}

File Metadata

Mime Type
text/plain
Expires
Sun, Jul 19, 8:48 AM (5 h, 1 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35228407
Default Alt Text
D57355.id178973.diff (4 KB)

Event Timeline