Page MenuHomeFreeBSD

D57355.id.diff
No OneTemporary

D57355.id.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,12 @@
*/
#include "namespace.h"
+#include <sys/param.h>
#include <assert.h>
#include <errno.h>
#include <limits.h>
+#include <stdbool.h>
+#include <stdckdint.h>
#ifdef DEBUG
#include <stdint.h>
#endif
@@ -62,7 +65,15 @@
else
newsize = newoff;
if (newsize > ms->size) {
- buf = realloc(*ms->bufp, newsize + 1);
+ size_t growsize;
+
+ if (ckd_add(&growsize, ms->size, ms->size / 2))
+ growsize = SSIZE_MAX - 1;
+
+ /* 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 +81,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,12 @@
*/
#include "namespace.h"
+#include <sys/param.h>
#include <assert.h>
#include <errno.h>
#include <limits.h>
+#include <stdbool.h>
+#include <stdckdint.h>
#ifdef DEBUG
#include <stdint.h>
#endif
@@ -63,17 +66,26 @@
else
newsize = newoff;
if (newsize > ms->size) {
- buf = reallocarray(*ms->bufp, newsize + 1, sizeof(wchar_t));
+ size_t growsize;
+
+ if (ckd_add(&growsize, ms->size, ms->size / 2))
+ growsize = SSIZE_MAX - 1;
+
+ /* 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,45 @@
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(resize_test);
+ATF_TC_HEAD(resize_test, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Tests that memstream growth doesn't move SEEK_END too far");
+}
+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 +231,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,50 @@
fclose(fp);
}
+ATF_TC(resize_test);
+ATF_TC_HEAD(resize_test, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Tests that wmemstream growth doesn't move SEEK_END too far");
+}
+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, 7:39 AM (16 h, 7 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35216523
Default Alt Text
D57355.id.diff (5 KB)

Event Timeline