about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog3
-rw-r--r--libio/fmemopen.c16
-rw-r--r--stdio-common/tst-fmemopen2.c67
3 files changed, 84 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index acf97b2f98..66a6f02297 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
 2005-01-05  Ulrich Drepper  <drepper@redhat.com>
 
+	* libio/fmemopen.c (fmemopen_seek): SEEK_END should count from
+	maximum used address, not maximum buffer position.
+
 	* libio/iofopncook.c (_IO_cookie_seekoff): Define.  Mark offset as
 	invalid to disable optimizations in fileops which won't work here.
 	(_IO_cookie_jumps): Use it.
diff --git a/libio/fmemopen.c b/libio/fmemopen.c
index 265b848ebe..51e849e846 100644
--- a/libio/fmemopen.c
+++ b/libio/fmemopen.c
@@ -164,7 +164,7 @@ fmemopen_seek (void *cookie, _IO_off64_t *p, int w)
       break;
 
     case SEEK_END:
-      np = c->size - *p;
+      np = c->maxpos - *p;
       break;
 
     default:
@@ -201,6 +201,13 @@ fmemopen (void *buf, size_t len, const char *mode)
   cookie_io_functions_t iof;
   fmemopen_cookie_t *c;
 
+  if (len == 0)
+    {
+    einval:
+      __set_errno (EINVAL);
+      return NULL;
+    }
+
   c = (fmemopen_cookie_t *) malloc (sizeof (fmemopen_cookie_t));
   if (c == NULL)
     return NULL;
@@ -218,7 +225,12 @@ fmemopen (void *buf, size_t len, const char *mode)
       c->buffer[0] = '\0';
     }
   else
-    c->buffer = buf;
+    {
+      if ((uintptr_t) len > -(uintptr_t) buf)
+	goto einval;
+
+      c->buffer = buf;
+    }
 
   c->size = len;
 
diff --git a/stdio-common/tst-fmemopen2.c b/stdio-common/tst-fmemopen2.c
new file mode 100644
index 0000000000..6a0ee836a2
--- /dev/null
+++ b/stdio-common/tst-fmemopen2.c
@@ -0,0 +1,67 @@
+#include <assert.h>
+#include <stdio.h>
+#include <sys/types.h>
+
+
+static int
+do_test (void)
+{
+  int result = 0;
+  char buf[100];
+  FILE *fp = fmemopen (buf, sizeof (buf), "w");
+  if (fp == NULL)
+    {
+      puts ("fmemopen failed");
+      return 0;
+    }
+  static const char str[] = "hello world";
+#define nstr (sizeof (str) - 1)
+  fputs (str, fp);
+  off_t o = ftello (fp);
+  if (o != nstr)
+    {
+      printf ("first ftello returned %ld, expected %zu\n", o, nstr);
+      result = 1;
+    }
+  rewind (fp);
+  o = ftello (fp);
+  if (o != 0)
+    {
+      printf ("second ftello returned %ld, expected %zu\n", o, 0);
+      result = 1;
+    }
+  if (fseeko (fp, 0, SEEK_END) != 0)
+    {
+      puts ("fseeko failed");
+      return 1;
+    }
+  o = ftello (fp);
+  if (o != nstr)
+    {
+      printf ("third ftello returned %ld, expected %zu\n", o, nstr);
+      result = 1;
+    }
+  rewind (fp);
+  static const char str2[] = "just hello";
+#define nstr2 (sizeof (str2) - 1)
+  assert (nstr2 < nstr);
+  fputs (str2, fp);
+  o = ftello (fp);
+  if (o != nstr2)
+    {
+      printf ("fourth ftello returned %ld, expected %zu\n", o, nstr2);
+      result = 1;
+    }
+  fclose (fp);
+  static const char str3[] = "just hellod";
+  if (strcmp (buf, str3) != 0)
+    {
+      printf ("final string is \"%s\", expected \"%s\"\n",
+              buf, str3);
+      result = 1;
+    }
+  return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"