On Tue, Nov 24, 2015 at 04:24:54PM +0000, Jean-Michel Vourgère wrote:
> Control: tags -1 + help
> 
> Antonio Terceiro wrote:
> > "make  check-TESTS" fails
> 
> I tested previous version on mips, and it now FTBFS too. It used to work
> ok. [1] (thanks Tobias, upstream, for suggesting that.)
> 
> So I suppose it is related to another package.
> 
> I tried compiling with good old gcc 4.9 and I get the same error in 1.5.4.

It's a latent bug in rrdtool that triggered with libc6 2.19-20 on mips.

The test suite failure in tests/tune2 boils down to

 rrdtool tune --beta 0.4 tests/tune2-testorg.rrd

zeroing out a big part of the file in addition to changing a single byte
like it's supposed to. It's easy to see by calling

 rrdtool dump tests/tune2-testorg.rrd >/dev/null

which starts to fail with stderr

 ERROR: unknown consolidation function ''

on a corrupted file.

This started to happen with libc6 2.19-20, as tested by compiling rrdtool
1.5.5 on jessie and running with LD_LIBRARY_PATH pointing to different
libc.so.6 versions.

The problem is that rrd_write() ends up calling memcpy(3) on overlapping
memory areas, which is explicitly prohibited in its documentation. With
libc6 2.19-20 on mips, this started zeroing out part of the areas under
some conditions. The attached testcase triggers it at least on minkus.d.o,
tested with something like

  #!/bin/bash
  dd if=/dev/urandom of=testfile.orig bs=1024 count=1
  gcc t.c
  cp testfile.orig testfile
  ./a.out testfile
  diff -u <(od -x testfile.orig) <(od -x testfile)
  
which normally doesn't show any differences.  I'm cc'ing the libc6
maintainers, not sure how intentional this change of behaviour is.

Backtrace for the rrd_write() call that triggers it:

  #0  rrd_write (rrd_file=0x41d038, buf=0x77fef168, count=560) at rrd_open.c:798
  #1  0x77f65888 in rrd_tune (argc=4, argv=0x7fff6648) at rrd_tune.c:395
  #2  0x00402f44 in HandleInputLine (argc=5, argv=0x7fff6644, out=0x77f56900 
<_IO_2_1_stderr_>) at rrd_tool.c:800
  #3  0x00400f10 in main (argc=5, argv=0x7fff6644) at rrd_tool.c:545
  
  (gdb) print ((rrd_simple_file_t *) rrd_file->pvt)->file_start + rrd_file->pos
  $6 = 0x77fef168 "HWPREDICT"
  
  (gdb) print (char *)buf
  $8 = 0x77fef168 "HWPREDICT"

A workaround is to configure with --disable-mmap, except that seems
to break tests/tune1 on all architectures (at least amd64 and mips).
I haven't looked into that.
-- 
Niko Tyni   nt...@debian.org
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <string.h>

#define MYSIZE 1024

int main(int argc, char **argv) {
    int fd;
    char *d;

    if (argc != 2) {
        fprintf(stderr, "file argument needed\n");
        exit(1);
    }
    fd = open(argv[1], O_RDWR);
    if (fd < 0)
        perror("open failed");
    d = mmap(NULL, MYSIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (!d)
        perror("mmap");
    memcpy(d+260, d+260, 355);
    if (munmap(d, MYSIZE) < 0)
        perror("munmap");
    return 0;
}

Reply via email to