[GH-ISSUE #491] Stack Buffer Overflow in lxw_datetime_to_excel_datetime() with Invalid Month Values #384

Closed
opened 2026-05-05 12:14:05 -06:00 by gitea-mirror · 2 comments
Owner

Originally created by @LkkkLxy on GitHub (Oct 11, 2025).
Original GitHub issue: https://github.com/jmcnamara/libxlsxwriter/issues/491

Originally assigned to: @jmcnamara on GitHub.

Description

A stack buffer overflow vulnerability exists in libxlsxwriter's datetime conversion function. When lxw_datetime_to_excel_datetime() is called with a month value greater than 12, the function accesses beyond the bounds of the mdays array, causing a stack buffer overflow.

Steps to Reproduce

Environment

  • OS: Linux (tested on Ubuntu with Docker)
  • libxlsxwriter version: Current git master
  • Compiler: clang with AddressSanitizer

Compilation Command

clang test_datetime_crash.c -o test_datetime_crash \
    -fsanitize=address \
    -I/path/to/libxlsxwriter/include \
    /path/to/libxlsxwriter.a \
    -lz -lm

Minimal Test Case

#include <xlsxwriter.h>
#include <stdio.h>

int main() {
    lxw_datetime datetime = {
        .year = 2024,
        .month = 100,  // Invalid: must be 1-12
        .day = 1,
        .hour = 0,
        .min = 0,
        .sec = 0.0
    };
    
    printf("Testing datetime with month = %d\n", datetime.month);
    
    // This triggers stack buffer overflow
    double result = lxw_datetime_to_excel_datetime(&datetime);
    
    printf("Result: %f\n", result);
    return 0;
}

Expected Behavior

The library should:

  1. Validate that month is in the range 1-12
  2. Return an error or default value for invalid input
  3. Not crash or access memory outside of allocated buffers

Actual Behavior

The program crashes with a stack buffer overflow:

Testing datetime with month = 100
=================================================================
==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ff9ff3000d0
READ of size 16 at 0x7ff9ff3000d0 thread T0
    #0 0x556a4308c5ad in lxw_datetime_to_excel_date_with_epoch /src/libxlsxwriter/src/utility.c:411:17

Address 0x7ff9ff3000d0 is located in stack of thread T0 at offset 80 in frame
    #0 0x556a4308bd2f in lxw_datetime_to_excel_date_with_epoch /src/libxlsxwriter/src/utility.c:342

  This frame has 1 object(s):
    [32, 84) 'mdays' (line 355) <== Memory access at offset 80 partially overflows this variable

SUMMARY: AddressSanitizer: stack-buffer-overflow /src/libxlsxwriter/src/utility.c:411:17 in lxw_datetime_to_excel_date_with_epoch

Root Cause

In src/utility.c function lxw_datetime_to_excel_date_with_epoch(), line 411:

int mdays[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
// mdays has only 13 elements (indices 0-12)

// ...

/* Add days for previous months. */
for (i = 0; i < month; i++) {
    days += mdays[i];  // No bounds check on month value
}

The function reads datetime->month from user input but does not validate it before using it as a loop bound to access the mdays array. When month > 12, the loop accesses beyond the array bounds.

Call Stack

#0  lxw_datetime_to_excel_date_with_epoch() at utility.c:411:17
#1  lxw_datetime_to_excel_datetime()
#2  User code

Proposed Fix

Add input validation at the start of lxw_datetime_to_excel_date_with_epoch():

double lxw_datetime_to_excel_date_with_epoch(lxw_datetime *datetime,
                                               uint8_t use_1904_epoch)
{
    int month = datetime->month;
    int day = datetime->day;
    
    // Validate datetime components
    if (month < 1 || month > 12) {
        LXW_WARN("lxw_datetime_to_excel_date: invalid month %d (must be 1-12)", month);
        return 0.0;  // or return error code
    }
    
    if (day < 1 || day > 31) {
        LXW_WARN("lxw_datetime_to_excel_date: invalid day %d (must be 1-31)", day);
        return 0.0;
    }
    
    // Year validation
    if (datetime->year < 1900 || datetime->year > 9999) {
        LXW_WARN("lxw_datetime_to_excel_date: invalid year %d", datetime->year);
        return 0.0;
    }
    
    // Continue with existing implementation...
}

Additional Information

This bug is detected by fuzzing.

Originally created by @LkkkLxy on GitHub (Oct 11, 2025). Original GitHub issue: https://github.com/jmcnamara/libxlsxwriter/issues/491 Originally assigned to: @jmcnamara on GitHub. ## Description A stack buffer overflow vulnerability exists in libxlsxwriter's datetime conversion function. When `lxw_datetime_to_excel_datetime()` is called with a `month` value greater than 12, the function accesses beyond the bounds of the `mdays` array, causing a stack buffer overflow. ## Steps to Reproduce ### Environment - **OS**: Linux (tested on Ubuntu with Docker) - **libxlsxwriter version**: Current git master - **Compiler**: clang with AddressSanitizer ### Compilation Command ```bash clang test_datetime_crash.c -o test_datetime_crash \ -fsanitize=address \ -I/path/to/libxlsxwriter/include \ /path/to/libxlsxwriter.a \ -lz -lm ``` ### Minimal Test Case ```c #include <xlsxwriter.h> #include <stdio.h> int main() { lxw_datetime datetime = { .year = 2024, .month = 100, // Invalid: must be 1-12 .day = 1, .hour = 0, .min = 0, .sec = 0.0 }; printf("Testing datetime with month = %d\n", datetime.month); // This triggers stack buffer overflow double result = lxw_datetime_to_excel_datetime(&datetime); printf("Result: %f\n", result); return 0; } ``` ### Expected Behavior The library should: 1. Validate that `month` is in the range 1-12 2. Return an error or default value for invalid input 3. Not crash or access memory outside of allocated buffers ### Actual Behavior The program crashes with a stack buffer overflow: ``` Testing datetime with month = 100 ================================================================= ==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ff9ff3000d0 READ of size 16 at 0x7ff9ff3000d0 thread T0 #0 0x556a4308c5ad in lxw_datetime_to_excel_date_with_epoch /src/libxlsxwriter/src/utility.c:411:17 Address 0x7ff9ff3000d0 is located in stack of thread T0 at offset 80 in frame #0 0x556a4308bd2f in lxw_datetime_to_excel_date_with_epoch /src/libxlsxwriter/src/utility.c:342 This frame has 1 object(s): [32, 84) 'mdays' (line 355) <== Memory access at offset 80 partially overflows this variable SUMMARY: AddressSanitizer: stack-buffer-overflow /src/libxlsxwriter/src/utility.c:411:17 in lxw_datetime_to_excel_date_with_epoch ``` ## Root Cause In `src/utility.c` function `lxw_datetime_to_excel_date_with_epoch()`, line 411: ```c int mdays[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; // mdays has only 13 elements (indices 0-12) // ... /* Add days for previous months. */ for (i = 0; i < month; i++) { days += mdays[i]; // No bounds check on month value } ``` The function reads `datetime->month` from user input but does not validate it before using it as a loop bound to access the `mdays` array. When `month > 12`, the loop accesses beyond the array bounds. ### Call Stack ``` #0 lxw_datetime_to_excel_date_with_epoch() at utility.c:411:17 #1 lxw_datetime_to_excel_datetime() #2 User code ``` ## Proposed Fix Add input validation at the start of `lxw_datetime_to_excel_date_with_epoch()`: ```c double lxw_datetime_to_excel_date_with_epoch(lxw_datetime *datetime, uint8_t use_1904_epoch) { int month = datetime->month; int day = datetime->day; // Validate datetime components if (month < 1 || month > 12) { LXW_WARN("lxw_datetime_to_excel_date: invalid month %d (must be 1-12)", month); return 0.0; // or return error code } if (day < 1 || day > 31) { LXW_WARN("lxw_datetime_to_excel_date: invalid day %d (must be 1-31)", day); return 0.0; } // Year validation if (datetime->year < 1900 || datetime->year > 9999) { LXW_WARN("lxw_datetime_to_excel_date: invalid year %d", datetime->year); return 0.0; } // Continue with existing implementation... } ``` ## Additional Information This bug is detected by fuzzing.
gitea-mirror 2026-05-05 12:14:05 -06:00
  • closed this issue
  • added the
    bug
    label
Author
Owner

@jmcnamara commented on GitHub (Oct 13, 2025):

Thanks. I'll look into that.

<!-- gh-comment-id:3396399983 --> @jmcnamara commented on GitHub (Oct 13, 2025): Thanks. I'll look into that.
Author
Owner

@jmcnamara commented on GitHub (Oct 31, 2025):

Fixed on main. Thanks.

<!-- gh-comment-id:3471896332 --> @jmcnamara commented on GitHub (Oct 31, 2025): Fixed on main. Thanks.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: github-starred/libxlsxwriter#384
No description provided.