jgarff / rpi_ws281x

Userspace Raspberry Pi PWM library for WS281X LEDs
BSD 2-Clause "Simplified" License
1.76k stars 615 forks source link

munmap_chunk(): invalid pointer #525

Closed godmar closed 8 months ago

godmar commented 8 months ago

I'm using rpi-ws281x 5.0.0 on an RPi 3b with Raspbian GNU/Linux 11 via Python. My Python program does not use any other native libraries besides this one. In my app, I'm using 2 PWM channels (GPIO 18 and 19) and one 1 PCM channel (GPIO 21), and the app/hardware basically works.

When exiting, I'm seeing:

munmap_chunk(): invalid pointer

Program received signal SIGABRT, Aborted.
__GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
50  ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1  0x76d4a364 in __GI_abort () at abort.c:79
#2  0x76d9be44 in __libc_message (action=action@entry=do_abort, fmt=<optimized out>)
    at ../sysdeps/posix/libc_fatal.c:155
#3  0x76da39fc in malloc_printerr (str=<optimized out>) at malloc.c:5347
#4  0x76da3d40 in munmap_chunk (p=<optimized out>) at malloc.c:2830
#5  0x766b0230 in ws2811_cleanup (ws2811=0x51e7e8) at lib/ws2811.c:623
#6  0x766b54d0 in _wrap_ws2811_fini (self=<optimized out>, args=<optimized out>)
    at rpi_ws281x_wrap.c:4169
#7  0x000b747c in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)

This crash would occur here.

This appears to be in the PCM mode driver for GPIO 21:

(gdb) p *ws2811
$1 = {render_wait_time = 5700, device = 0x4fc5d8, rpi_hw = 0x766cae2c <rpi_hw_info+1140>, 
  freq = 800000, dmanum = 10, channel = {{gpionum = 21, invert = 0, count = 180, 
      strip_type = 528384, leds = 0x4e16a8, brightness = 15 '\017', wshift = 0 '\000', 
      rshift = 8 '\b', gshift = 16 '\020', bshift = 0 '\000', gamma = 0x4cf250 ""}, {gpionum = 0, 
      invert = 0, count = 0, strip_type = 1050624, leds = 0x4cf358, brightness = 0 '\000', 
      wshift = 0 '\000', rshift = 16 '\020', gshift = 8 '\b', bshift = 0 '\000', 
      gamma = 0x5082c8 ""}}}
(gdb) p *ws2811->device
$3 = {driver_mode = 2, pxl_raw = 0x76fb2020 <error: Cannot access memory at address 0x76fb2020>, 
  dma = 0x76fb1a00, pwm = 0x0, pcm = 0x76fb0000, spi_fd = 0, dma_cb = 0x76fb2000, 
  dma_cb_addr = 4273229824, gpio = 0x76faf000, cm_clk = 0x76fae098, mbox = {handle = 4, 
    mem_ref = 73, bus_addr = 4273229824, size = 4096, 
    virt_addr = 0x76fb2000 <error: Cannot access memory at address 0x76fb2000>}, max_count = 180}

ws2811_init calls check_hwver_and_gpionum which calls set_driver_mode based on the pin number.

set_driver_mode contains this line:

    // For PCM and SPI zero the 2nd channel
    memset(&ws2811->channel[1], 0, sizeof(ws2811_channel_t));

which should set ws2811->channels[1].leds to NULL initially along with the rest of the channel 1 struct.

Later in ws2811_init allocates 2 LED buffers (based on RPI_PWM_CHANNELS) even if the driver is in PCM mode. This shouldn't be an issue though.

I don't immediately see an issue with the logic here, so there must be a memory corruption issue elsewhere.

godmar commented 8 months ago

Issue found. The Python wrapper does not perform a proper bounds check when setting pixels, leading to memory corruption. I'll file a bug with them.

See also