Bug 1125616

Summary: [stagnig] syslinux fails to build due aliasing bugs in lzo
Product: [openSUSE] openSUSE Tumbleweed Reporter: Dominique Leuenberger <dimstar>
Component: BasesystemAssignee: Steffen Winterfeldt <snwint>
Status: RESOLVED FIXED QA Contact: E-mail List <qa-bugs>
Severity: Normal    
Priority: P3 - Medium CC: matz, mliska
Version: Current   
Target Milestone: ---   
Hardware: Other   
OS: Other   
URL: https://trello.com/c/rzsdpWo2
Whiteboard:
Found By: --- Services Priority:
Business Priority: Blocker: ---
Marketing QA Status: --- IT Deployment: ---

Description Dominique Leuenberger 2019-02-15 15:40:46 UTC
Binutils 2.32 has been staged and is making good progress.

One package failing to build in this setup is syslinux (on i586)

The build log ends with:

>[  132s] objdump -h ldlinux.elf > ldlinux.sec
>[  132s] perl lstadjust.pl ldlinux.lsr ldlinux.sec ldlinux.lst
>[  132s] objcopy -O binary ldlinux.elf ldlinux.raw
>[  132s] ../lzo/prepcore ldlinux.raw ldlinux.bin
>[  132s] ../lzo/prepcore: ldlinux.raw: internal error - lzo_init() failed!
>[  132s] make[1]: *** [Makefile:86: ldlinux.bin] Error 1
>[  132s] rm ldlinux.o
>[  132s] make[1]: Leaving directory '/home/abuild/rpmbuild/BUILD/syslinux-4.04/core'
>[  132s] make: *** [Makefile:88: all] Error 2
>[  132s] error: Bad exit status from /var/tmp/rpm-tmp.k5I91R (%build)
Comment 1 Michael Matz 2019-02-15 16:34:07 UTC
This has nothing to do with binutils.  What actually happens is that LZO contains non-conforming code that does or doesn't work depending on the
phase of the moon.  We seemed to have been lucky until now.

lzo/src/lzo_init.c, routine _lzo_config_check is broken.  It effectively
does this:

------------ snip ----------------
typedef int lzo_bool;
typedef unsigned long lzo_uint;
typedef unsigned int lzo_uint32;

int __attribute__((noipa))
_lzo_config_check(void)
{
    lzo_bool r = 1;
    union { unsigned char c[2*sizeof(lzo_uint)]; lzo_uint l[2]; } u;
    unsigned long p;

    u.l[0] = u.l[1] = 0; u.c[0] = 128;
    r &= (u.l[0] == 128);

    p = (unsigned long) (const void *) &u.c[0];
    u.l[0] = u.l[1] = 0;
    r &= ((* (const unsigned short *) (p+1)) == 0);

    p = (unsigned long) (const void *) &u.c[0];
    u.l[0] = u.l[1] = 0;
    r &= ((* (const lzo_uint32 *) (p+1)) == 0);

    return r == 1 ? 0 : (-1);
}

extern int printf (const char *, ...);
int main()
{
  if (_lzo_config_check() != 0)
    printf("broken\n");
  return 0;
}
------------ snap --------------

The two accesses to 'p+1' are wrong: it tries to read memory as a short or
uint32, which was written to as an long before (the write to u.l[1]).  The store
and the loads don't alias (because of different types) and GCC is free to
remove the stores, which it does with -Os and -O2.  The load then accesses
uninitialized stack memory and the check might or might not succeed.

You could compile lzo_init.c with -fno-strict-aliasing, or better yet
fix this routine to be written in ISO C.  As LZO is like it is, there
might be other similar aliasing bugs lurking so maybe it's better to just
addd -fno-strict-aliasing, though.
Comment 2 Steffen Winterfeldt 2019-02-18 12:01:53 UTC
Tracking in YaST Scrum board.
Comment 3 Steffen Winterfeldt 2019-02-18 14:09:49 UTC
fix submitted
Comment 4 Swamp Workflow Management 2019-02-18 14:50:10 UTC
This is an autogenerated message for OBS integration:
This bug (1125616) was mentioned in
https://build.opensuse.org/request/show/677142 Factory / syslinux