This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: [PATCH v2] ftell: seek to end only when there are unflushed bytes (BZ #17647)
- From: Adhemerval Zanella <azanella at linux dot vnet dot ibm dot com>
- To: libc-alpha at sourceware dot org
- Cc: Siddhesh Poyarekar <siddhesh at redhat dot com>, "Carlos O'Donell" <carlos at redhat dot com>
- Date: Fri, 05 Dec 2014 10:05:44 -0200
- Subject: Re: [PATCH v2] ftell: seek to end only when there are unflushed bytes (BZ #17647)
- Authentication-results: sourceware.org; auth=none
- References: <20141125155404 dot GO12197 at spoyarek dot pnq dot redhat dot com> <547FC7C7 dot 4030000 at redhat dot com> <54805EAD dot 3000605 at linux dot vnet dot ibm dot com> <54808488 dot 1050602 at redhat dot com> <54809D11 dot 5040406 at linux dot vnet dot ibm dot com>
On 04-12-2014 15:42, Adhemerval Zanella wrote:
> On 04-12-2014 13:58, Carlos O'Donell wrote:
>> On 12/04/2014 08:16 AM, Adhemerval Zanella wrote:
>>> ftell: fdopen (file, "a+"): old offset = 0, new offset = 30, offset after EOF = 36
>>> ftell: fopen (file, "(null)"):
>>> Program received signal SIGSEGV, Segmentation fault.
>>> _IO_new_file_fopen (fp=0x212a2620, filename=0x212a0010 "/tmp/tst-active-handler-tmp.oSQlBj", mode=0x0, is32not64=1) at fileops.c:261
>>> 261 switch (*mode)
>>> (gdb) bt
>>> #0 _IO_new_file_fopen (fp=0x212a2620, filename=0x212a0010 "/tmp/tst-active-handler-tmp.oSQlBj", mode=0x0, is32not64=1) at fileops.c:261
>>> #1 0x00003fffb7e7ee7c in __fopen_internal (filename=0x212a0010 "/tmp/tst-active-handler-tmp.oSQlBj", mode=0x0, is32=<optimized out>) at iofopen.c:86
>>> #2 0x00003fffb7e7ef14 in _IO_new_fopen (filename=<optimized out>, mode=<optimized out>) at iofopen.c:97
>>> #3 0x0000000010001f88 in ?? ()
>>> #4 0x000000001000323c in ?? ()
>>> #5 0x000000001000180c in ?? ()
>>> #6 0x00003fffb7e2436c in generic_start_main (main=0x10015178, argc=<optimized out>, argv=0x3fffffffeb30, auxvec=0x3fffffffece0, init=<optimized out>, rtld_fini=<optimized out>,
>>> stack_end=<optimized out>, fini=<optimized out>) at ../csu/libc-start.c:289
>>> #7 0x00003fffb7e24594 in __libc_start_main (argc=<optimized out>, argv=<optimized out>, ev=<optimized out>, auxvec=<optimized out>, rtld_fini=<optimized out>, stinfo=<optimized out>,
>>> stack_on_entry=<optimized out>) at ../sysdeps/unix/sysv/linux/powerpc/libc-start.c:80
>>> #8 0x0000000000000000 in ?? ()
>>>
>>> GLIBC built with GCC 4.9.3 / -O3 (I have not tested different compiler/flags). I tried to
>>> debug a little and seems the test_modes is bogus somehow. The testcase also fails running
>>> on system GLIBC (2.17/FC19 in my environment).
>> We would have seen this in our internal ppc/ppc64 builds, but we didn't
>> which means it is likely compiler dependent.
>>
>> I assume that when you say FC19 you still mean a ppc64 FC19? Similar
>> compiler issue?
>>
>> I've kicked off a ppc64le build of master to see what I can see.
> I also thinks it is a codegen issue I am seeing, although valgrind did not report
> any meaningful issue besides the invalid memory access itself. I will check more
> today.
I just debug a little and my understanding is I am seeing a buffer overrun on the stack
allocated variable:
365 if (test_modes[i].fd_mode != O_WRONLY)
366 {
367 char tmpbuf[data_len];
368
369 rewind (fp);
370
371 while (fgets_func (tmpbuf, sizeof (tmpbuf), fp) && !feof (fp));
The 'data_len' is calculated with wsclen and allocated as 'char'. The subsequent fgetws
will then try to write at most 'data_len' wchar_t in a buffer with just data_len 'char'.
The following patch fix the issues I am seeing on powerpc64:
diff --git a/libio/tst-ftell-active-handler.c b/libio/tst-ftell-active-handler.c
index f69e169..44a4fac 100644
--- a/libio/tst-ftell-active-handler.c
+++ b/libio/tst-ftell-active-handler.c
@@ -84,6 +84,7 @@ static const char *char_data = "abcdef";
static const wchar_t *wide_data = L"abcdef";
static size_t data_len;
static size_t file_len;
+static size_t char_len;
typedef int (*fputs_func_t) (const void *data, FILE *fp);
typedef void *(*fgets_func_t) (void *ws, int n, FILE *fp);
@@ -364,11 +365,11 @@ do_ftell_test (const char *filename)
reading. */
if (test_modes[i].fd_mode != O_WRONLY)
{
- char tmpbuf[data_len];
+ char tmpbuf[data_len * char_len];
rewind (fp);
- while (fgets_func (tmpbuf, sizeof (tmpbuf), fp) && !feof (fp));
+ while (fgets_func (tmpbuf, data_len, fp) && !feof (fp));
write_ret = write (fd, data, data_len);
if (write_ret != data_len)
@@ -656,6 +657,7 @@ do_test (void)
fgets_func = (fgets_func_t) fgets;
data = char_data;
data_len = strlen (char_data);
+ char_len = sizeof (char);
ret |= do_one_test (filename);
/* Truncate the file before repeating the tests in wide mode. */
@@ -678,6 +680,7 @@ do_test (void)
fgets_func = (fgets_func_t) fgetws;
data = wide_data;
data_len = wcslen (wide_data);
+ char_len = sizeof (wchar_t);
ret |= do_one_test (filename);
return ret;
What do you think?