Page MenuHomeFreeBSD

D57355.id183194.diff
No OneTemporary

D57355.id183194.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 <stdckdint.h>
#ifdef DEBUG
#include <stdint.h>
#endif
@@ -55,13 +57,20 @@
memstream_grow(struct memstream *ms, fpos_t newoff)
{
char *buf;
- ssize_t newsize;
+ ssize_t newlen;
if (newoff < 0 || newoff >= SSIZE_MAX)
- newsize = SSIZE_MAX - 1;
+ newlen = SSIZE_MAX - 1;
else
- newsize = newoff;
- if (newsize > ms->size) {
+ newlen = newoff;
+ if (newlen > ms->size) {
+ size_t newsize;
+
+ if (ckd_add(&newsize, ms->size, ms->size / 2))
+ newsize = SSIZE_MAX - 1;
+
+ newsize = MAX(newsize, newlen);
+
buf = realloc(*ms->bufp, newsize + 1);
if (buf == NULL)
return (0);
@@ -75,8 +84,8 @@
ms->size = newsize;
}
- if (newsize > ms->len)
- ms->len = newsize;
+ if (newlen > ms->len)
+ ms->len = newlen;
return (1);
}
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 <stdckdint.h>
#ifdef DEBUG
#include <stdint.h>
#endif
@@ -56,13 +58,20 @@
wmemstream_grow(struct wmemstream *ms, fpos_t newoff)
{
wchar_t *buf;
- ssize_t newsize;
+ ssize_t newlen;
if (newoff < 0 || newoff >= SSIZE_MAX / sizeof(wchar_t))
- newsize = SSIZE_MAX / sizeof(wchar_t) - 1;
+ newlen = SSIZE_MAX / sizeof(wchar_t) - 1;
else
- newsize = newoff;
- if (newsize > ms->size) {
+ newlen = newoff;
+ if (newlen > ms->size) {
+ size_t newsize;
+
+ if (ckd_add(&newsize, ms->size, ms->size / 2))
+ newsize = SSIZE_MAX - 1;
+
+ newsize = MAX(newsize, newlen);
+
buf = reallocarray(*ms->bufp, newsize + 1, sizeof(wchar_t));
if (buf == NULL)
return (0);
@@ -74,8 +83,9 @@
*ms->bufp = buf;
ms->size = newsize;
}
- if (newsize > ms->len)
- ms->len = newsize;
+
+ if (newlen > ms->len)
+ ms->len = newlen;
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
Thu, Sep 3, 10:11 AM (5 h, 8 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
37804352
Default Alt Text
D57355.id183194.diff (5 KB)

Event Timeline