@@ -1,3 +1,11 @@
+2016-04-27 Adhemerval Zanella <adhemerval.zanella@linaro.org>
+
+ [BZ #20012]
+ * libio/fmemopen.c (fmemopen_read): Use buffer maximum position, not
+ length to calculate the buffer to read.
+ (fmemopen_write): Set the buffer position based on bytes written.
+ (fmemopen_seek): Return EINVAL for invalid whence modes.
+
2016-04-27 Florian Weimer <fweimer@redhat.com>
[BZ #19831]
@@ -50,16 +50,14 @@ fmemopen_read (void *cookie, char *b, size_t s)
if (c->pos + s > c->maxpos)
{
- if ((size_t) c->pos == c->maxpos)
- return 0;
- s = c->size - c->pos;
+ s = c->maxpos - c->pos;
+ if ((size_t) c->pos > c->maxpos)
+ s = 0;
}
memcpy (b, &(c->buffer[c->pos]), s);
c->pos += s;
- if ((size_t) c->pos > c->maxpos)
- c->maxpos = c->pos;
return s;
}
@@ -86,7 +84,7 @@ fmemopen_write (void *cookie, const char *b, size_t s)
memcpy (&(c->buffer[pos]), b, s);
- c->pos += s;
+ c->pos = pos + s;
if ((size_t) c->pos > c->maxpos)
{
c->maxpos = c->pos;
@@ -123,7 +121,10 @@ fmemopen_seek (void *cookie, _IO_off64_t *p, int w)
}
if (np < 0 || (size_t) np > c->size)
- return -1;
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
*p = c->pos = np;
@@ -186,6 +186,97 @@ do_test_read_seek_negative (void)
}
static int
+do_test_write_append_2 (void)
+{
+ char buf[10] = "test";
+ FILE *fp = fmemopen (buf, 10, "a+");
+ size_t r = ftell (fp);
+ size_t e = strlen (buf);
+ if (r != e)
+ {
+ printf ("%s: ftell returned %zu, expected %zu\n", __FUNCTION__, r, e);
+ return 1;
+ }
+
+ if (fseek (fp, 0, SEEK_SET) == -1)
+ {
+ printf ("%s: fseek returned -1\n", __FUNCTION__);
+ return 1;
+ }
+
+ int gr;
+ if ((gr = getc (fp)) != 't' ||
+ (gr = getc (fp)) != 'e' ||
+ (gr = getc (fp)) != 's' ||
+ (gr = getc (fp)) != 't' ||
+ (gr = getc (fp)) != EOF)
+ {
+ printf ("%s: getc failed returned %i\n", __FUNCTION__, gr);
+ return 1;
+ }
+
+ if (fseek (fp, e+1, SEEK_SET) == -1)
+ {
+ printf ("%s: fseek returned -1\n", __FUNCTION__);
+ return 1;
+ }
+
+ if ((r = ftell (fp)) != e+1)
+ {
+ printf ("%s: ftell returned %zu, expected %zu\n", __FUNCTION__, r, e+1);
+ return 1;
+ }
+
+ if ((gr = getc (fp)) != EOF)
+ {
+ printf ("%s: getc failed returned %i\n", __FUNCTION__, gr);
+ return 1;
+ }
+
+ /* Check if internal position is not changed with a getc returning EOF. */
+ if ((r = ftell (fp)) != e+1)
+ {
+ printf ("%s: ftell returned %zu, expected %zu\n", __FUNCTION__, r, e+1);
+ return 1;
+ }
+
+ if (fseek (fp, 0, SEEK_CUR) == -1)
+ {
+ printf ("%s: fseek returned -1\n", __FUNCTION__);
+ return 1;
+ }
+
+ /* This should be overwritten by fprintf + fflush. */
+ buf[e+2] = 'X';
+
+ if ((r = fprintf (fp, "%d", 101)) != 3)
+ {
+ printf ("%s: fprintf returned %zu, expected %d\n", __FUNCTION__, r, 3);
+ return 1;
+ }
+
+ fflush (fp);
+
+ /* Check if internal position is changed by 3 (strlen of '101'). */
+ if ((r = ftell (fp)) != e+3)
+ {
+ printf ("%s: ftell returned %zu, expected %zu\n", __FUNCTION__, r, e+3);
+ return 1;
+ }
+
+ const char exp[] = "test101";
+ if (strcmp (buf, exp) != 0)
+ {
+ printf ("%s: check failed: %s != %s\n", __FUNCTION__, buf, exp);
+ return 1;
+ }
+
+ fclose(fp);
+
+ return 0;
+}
+
+static int
do_test (void)
{
int ret = 0;
@@ -199,6 +290,8 @@ do_test (void)
ret += do_test_read_seek_negative ();
+ ret += do_test_write_append_2 ();
+
return ret;
}