Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package limine for openSUSE:Factory checked in at 2025-12-29 15:17:06 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/limine (Old) and /work/SRC/openSUSE:Factory/.limine.new.1928 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "limine" Mon Dec 29 15:17:06 2025 rev:29 rq:1324621 version:10.6.0 Changes: -------- --- /work/SRC/openSUSE:Factory/limine/limine.changes 2025-12-27 11:29:42.641674156 +0100 +++ /work/SRC/openSUSE:Factory/.limine.new.1928/limine.changes 2025-12-29 15:18:07.002246516 +0100 @@ -1,0 +2,17 @@ +Sun Dec 28 23:48:58 UTC 2025 - Marvin Friedrich <[email protected]> + +- Update to 10.6.0: + * ISO9660: Add support for large, multi-extent files. + * Unbreak BIOS booting from optical media with ISO9660 filesystems on + many platforms including QEMU. This was a regression introduced in + 10.5.1. + * Fix an issue with large (>4GiB) physical memory allocations on 32-bit + platforms. Some values were truncated to size_t (aka uint32_t) in + many instances causing bugs. + * Fix a couple of memory leaks missed in 10.5.1. + * Add safeguard against the font file being too small for the expected + size. This avoids potential panics from the filesystem driver, and it + instead just prints a warning and falls back to using the default + font. + +------------------------------------------------------------------- Old: ---- limine-10.5.1.tar.gz New: ---- limine-10.6.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ limine.spec ++++++ --- /var/tmp/diff_new_pack.AG1HBh/_old 2025-12-29 15:18:07.654273316 +0100 +++ /var/tmp/diff_new_pack.AG1HBh/_new 2025-12-29 15:18:07.658273480 +0100 @@ -15,7 +15,7 @@ # Name: limine -Version: 10.5.1 +Version: 10.6.0 Release: 0 Summary: Modern, advanced, portable, multiprotocol bootloader and boot manager License: BSD-2-Clause ++++++ limine-10.5.1.tar.gz -> limine-10.6.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/limine-10.5.1/CONFIG.md new/limine-10.6.0/CONFIG.md --- old/limine-10.5.1/CONFIG.md 2025-12-26 15:00:56.000000000 +0100 +++ new/limine-10.6.0/CONFIG.md 2025-12-28 15:18:08.000000000 +0100 @@ -155,11 +155,13 @@ whole glyph by default; see `term_font_size`). See e.g. the [VGA text mode font](https://github.com/viler-int10h/vga-text-mode-fonts) collection for fonts. -* `term_font_size` - The size of the font in dots, which must correspond to the - font file or the display will be garbled. Note that glyphs are always one - byte wide, and columns over 8 are empty. Many fonts may be used in both 8- - and 9-dot wide variants. Defaults to `8x16`. Ignored if `term_font` not set - or if the font fails to load. +* `term_font_size` - The size of each glyph of the font in dots, which must + correspond to the font file, or display will be garbled or loading issues + will occur. Since it is assumed that all fonts are of width 8, the first + value of the pair (AKA the `8` in `8x16`) is effectively ignored. To set + horizontal spacing between glyphs on screen, see `term_font_spacing`. + Defaults to `8x16`. Ignored if `term_font` not set or if the font fails to + load. * `term_font_scale` - Scaling for the font in the x and y directions. `2x2` would display the font in double size, which is useful on high-DPI displays at native resolution. `2x1` only makes the font twice as wide, similar to the @@ -167,10 +169,8 @@ resolution display. Values over 8 are disallowed. Default is no scaling, i.e. `1x1`. * `term_font_spacing` - Horizontal spacing, in pixels, between glyphs on - screen. It is equivalent to setting a font width of - `<specified width>+<this value>`, except this value is preserved even in case - font loading fails, and it also applies to the built-in Limine font. Defaults - to 1. 0 is allowed. + screen. Also applies to the built-in Limine font. Defaults to 1. 0 is + allowed. * `term_palette` - Specifies the colour palette used by the terminal (RRGGBB). It is a `;` separated array of 8 colours: black, red, green, brown, blue, magenta, cyan, and gray. Ignored if not using a graphical terminal. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/limine-10.5.1/ChangeLog new/limine-10.6.0/ChangeLog --- old/limine-10.5.1/ChangeLog 2025-12-26 15:00:56.000000000 +0100 +++ new/limine-10.6.0/ChangeLog 2025-12-28 15:18:08.000000000 +0100 @@ -1,3 +1,29 @@ +2025-12-28 Mintsuki <[email protected]> + + *** Release 10.6.0 *** + + Noteworthy changes compared to the previous release, 10.5.1: + + New features: + - ISO9660: Add support for large, multi-extent files. + + Bug fixes: + - Unbreak BIOS booting from optical media with ISO9660 filesystems on + many platforms including QEMU. This was a regression introduced in + 10.5.1. + - Fix an issue with large (>4GiB) physical memory allocations on 32-bit + platforms. Some values were truncated to size_t (aka uint32_t) in + many instances causing bugs. + - Fix a couple of memory leaks missed in 10.5.1. + - Add safeguard against the font file being too small for the expected + size. This avoids potential panics from the filesystem driver, and it + instead just prints a warning and falls back to using the default + font. + + Miscellaneous: + - Update description of the `term_font_size` and `term_font_spacing` + configuration options in CONFIG.md. + 2025-12-26 Mintsuki <[email protected]> *** Release 10.5.1 *** diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/limine-10.5.1/common/drivers/vga_textmode.c new/limine-10.6.0/common/drivers/vga_textmode.c --- old/limine-10.5.1/common/drivers/vga_textmode.c 2025-12-26 15:00:56.000000000 +0100 +++ new/limine-10.6.0/common/drivers/vga_textmode.c 2025-12-28 15:18:08.000000000 +0100 @@ -355,7 +355,7 @@ term->full_refresh(term); if (!managed) { - term->deinit(term, pmm_free); + term->deinit(term, pmm_free_size_t); pmm_free(terms, sizeof(void *)); terms_i = 0; terms = NULL; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/limine-10.5.1/common/fs/fat32.s2.c new/limine-10.6.0/common/fs/fat32.s2.c --- old/limine-10.5.1/common/fs/fat32.s2.c 2025-12-26 15:00:56.000000000 +0100 +++ new/limine-10.6.0/common/fs/fat32.s2.c 2025-12-28 15:18:08.000000000 +0100 @@ -1,5 +1,4 @@ #include <stdint.h> -#include <limits.h> #include <fs/fat32.h> #include <lib/misc.h> #include <drivers/disk.h> @@ -292,14 +291,24 @@ } break; } - case 16: + case 16: { *out = 0; - volume_read(context->part, out, fat_base + (uint64_t)cluster * sizeof(uint16_t), sizeof(uint16_t)); + uint64_t offset = (uint64_t)cluster * sizeof(uint16_t); + if (offset + sizeof(uint16_t) > fat_size) { + return -1; + } + volume_read(context->part, out, fat_base + offset, sizeof(uint16_t)); break; - case 32: - volume_read(context->part, out, fat_base + (uint64_t)cluster * sizeof(uint32_t), sizeof(uint32_t)); + } + case 32: { + uint64_t offset = (uint64_t)cluster * sizeof(uint32_t); + if (offset + sizeof(uint32_t) > fat_size) { + return -1; + } + volume_read(context->part, out, fat_base + offset, sizeof(uint32_t)); *out &= 0x0fffffff; break; + } default: __builtin_unreachable(); } @@ -654,10 +663,10 @@ for (unsigned int i = 0; i < SIZEOF_ARRAY(current_part) - 1; i++) { // Check for overflow before computing path index - if (current_index > UINT_MAX - i) { + unsigned int path_idx; + if (__builtin_add_overflow(i, current_index, &path_idx)) { return NULL; // Path index would overflow } - unsigned int path_idx = i + current_index; if (path[path_idx] == 0) { memcpy(current_part, path + current_index, i); @@ -671,10 +680,11 @@ memcpy(current_part, path + current_index, i); current_part[i] = 0; // Check for overflow before updating current_index - if (current_index > UINT_MAX - i - 1) { + unsigned int new_index; + if (__builtin_add_overflow(current_index, i + 1, &new_index)) { return NULL; // current_index would overflow } - current_index += i + 1; + current_index = new_index; expect_directory = true; found_terminator = true; break; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/limine-10.5.1/common/fs/file.s2.c new/limine-10.6.0/common/fs/file.s2.c --- old/limine-10.5.1/common/fs/file.s2.c 2025-12-26 15:00:56.000000000 +0100 +++ new/limine-10.6.0/common/fs/file.s2.c 2025-12-28 15:18:08.000000000 +0100 @@ -83,6 +83,9 @@ void fread(struct file_handle *fd, void *buf, uint64_t loc, uint64_t count) { if (fd->is_memfile) { + if (loc >= fd->size || count > fd->size - loc) { + panic(false, "fread: attempted out of bounds read"); + } memcpy(buf, fd->fd + loc, count); } else { fd->read(fd, buf, loc, count); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/limine-10.5.1/common/fs/iso9660.s2.c new/limine-10.6.0/common/fs/iso9660.s2.c --- old/limine-10.5.1/common/fs/iso9660.s2.c 2025-12-26 15:00:56.000000000 +0100 +++ new/limine-10.6.0/common/fs/iso9660.s2.c 2025-12-28 15:18:08.000000000 +0100 @@ -13,15 +13,24 @@ uint32_t root_size; }; -struct iso9660_file_handle { - struct iso9660_context *context; +struct iso9660_extent { uint32_t LBA; uint32_t size; }; +struct iso9660_file_handle { + struct iso9660_context *context; + uint64_t total_size; + uint32_t extent_count; + struct iso9660_extent *extents; +}; + +#define ISO9660_FLAG_MULTI_EXTENT 0x80 + #define ISO9660_FIRST_VOLUME_DESCRIPTOR 0x10 #define ISO9660_VOLUME_DESCRIPTOR_SIZE ISO9660_SECTOR_SIZE #define ROCK_RIDGE_MAX_FILENAME 255 +#define ISO9660_MAX_EXTENT_COUNT 65536 // --- Both endian structures --- struct BE16_t { uint16_t little, big; } __attribute__((packed)); @@ -246,6 +255,46 @@ return false; } +// Advance to the next directory entry in the buffer +// Returns NULL if no more entries or invalid entry +static struct iso9660_directory_entry *iso9660_next_entry(void *current, void *buffer_end) { + struct iso9660_directory_entry *entry = current; + + if (entry->length == 0) { + // Skip to next sector boundary + uintptr_t current_addr = (uintptr_t)current; + uintptr_t next_sector = ALIGN_UP(current_addr + 1, ISO9660_SECTOR_SIZE); + if (next_sector >= (uintptr_t)buffer_end) + return NULL; + entry = (struct iso9660_directory_entry *)next_sector; + if (entry->length == 0) + return NULL; + return entry; + } + + void *next = (uint8_t *)current + entry->length; + if (next >= buffer_end) + return NULL; + + entry = next; + + // Handle zero-length entries (padding at sector boundaries) + if (entry->length == 0) { + uintptr_t next_sector = ALIGN_UP((uintptr_t)next + 1, ISO9660_SECTOR_SIZE); + if (next_sector >= (uintptr_t)buffer_end) + return NULL; + entry = (struct iso9660_directory_entry *)next_sector; + if (entry->length == 0) + return NULL; + } + + // Validate minimum entry size + if (entry->length < sizeof(struct iso9660_directory_entry)) + return NULL; + + return entry; +} + static struct iso9660_directory_entry *iso9660_find(void *buffer, uint32_t size, const char *filename) { while (size) { struct iso9660_directory_entry *entry = buffer; @@ -367,8 +416,54 @@ next_sector = entry->extent.little; next_size = entry->extent_size.little; - if (*path == '\0') - break; // Found :) + if (*path == '\0') { + // Found the file - collect all extents for multi-extent files + void *buffer_end = (uint8_t *)current + current_size; + + // First pass: count extents and calculate total size + uint32_t extent_count = 1; + uint64_t total_size = entry->extent_size.little; + struct iso9660_directory_entry *e = entry; + + while (e->flags & ISO9660_FLAG_MULTI_EXTENT) { + struct iso9660_directory_entry *next = iso9660_next_entry(e, buffer_end); + if (next == NULL) + break; + e = next; + extent_count++; + total_size += e->extent_size.little; + + // Sanity check to prevent runaway on corrupted directories + if (extent_count >= ISO9660_MAX_EXTENT_COUNT) { + break; + } + } + + // Allocate extent array + ret->extents = ext_mem_alloc(extent_count * sizeof(struct iso9660_extent)); + ret->extent_count = extent_count; + ret->total_size = total_size; + + // Second pass: populate extent array + e = entry; + for (uint32_t i = 0; i < extent_count; i++) { + ret->extents[i].LBA = e->extent.little; + ret->extents[i].size = e->extent_size.little; + if (i + 1 < extent_count) { + struct iso9660_directory_entry *next = iso9660_next_entry(e, buffer_end); + if (next == NULL) + break; + e = next; + } + } + + // Free the directory buffer if we allocated one + if (!first) { + pmm_free(current, current_size); + } + + goto setup_handle; + } path++; // Skip the '/' separator @@ -401,15 +496,20 @@ pmm_free(current, current_size); } - ret->LBA = next_sector; - ret->size = next_size; + // Fallback path (trailing slash case) - create single extent + ret->extents = ext_mem_alloc(sizeof(struct iso9660_extent)); + ret->extent_count = 1; + ret->total_size = next_size; + ret->extents[0].LBA = next_sector; + ret->extents[0].size = next_size; +setup_handle:; struct file_handle *handle = ext_mem_alloc(sizeof(struct file_handle)); handle->fd = ret; handle->read = (void *)iso9660_read; handle->close = (void *)iso9660_close; - handle->size = ret->size; + handle->size = ret->total_size; handle->vol = vol; #if defined (UEFI) handle->efi_part_handle = vol->efi_part_handle; @@ -420,17 +520,41 @@ static void iso9660_read(struct file_handle *file, void *buf, uint64_t loc, uint64_t count) { struct iso9660_file_handle *f = file->fd; - uint64_t base_offset; - if (__builtin_mul_overflow((uint64_t)f->LBA, (uint64_t)ISO9660_SECTOR_SIZE, &base_offset)) { - panic(false, "iso9660: offset calculation overflow"); - } - uint64_t offset; - if (__builtin_add_overflow(base_offset, loc, &offset)) { - panic(false, "iso9660: offset calculation overflow"); + + // Find which extent 'loc' falls into and read across extents as needed + uint64_t extent_start = 0; + for (uint32_t i = 0; i < f->extent_count && count > 0; i++) { + uint64_t extent_size = f->extents[i].size; + uint64_t extent_end = extent_start + extent_size; + + if (loc < extent_end) { + // Read starts (or continues) in this extent + uint64_t offset_in_extent = (loc > extent_start) ? (loc - extent_start) : 0; + uint64_t bytes_available = extent_size - offset_in_extent; + uint64_t to_read = (count < bytes_available) ? count : bytes_available; + + uint64_t base_offset; + if (__builtin_mul_overflow((uint64_t)f->extents[i].LBA, (uint64_t)ISO9660_SECTOR_SIZE, &base_offset)) { + panic(false, "iso9660: offset calculation overflow"); + } + uint64_t disk_offset; + if (__builtin_add_overflow(base_offset, offset_in_extent, &disk_offset)) { + panic(false, "iso9660: offset calculation overflow"); + } + + volume_read(f->context->vol, buf, disk_offset, to_read); + + buf = (uint8_t *)buf + to_read; + loc += to_read; + count -= to_read; + } + + extent_start = extent_end; } - volume_read(f->context->vol, buf, offset, count); } static void iso9660_close(struct file_handle *file) { - pmm_free(file->fd, sizeof(struct iso9660_file_handle)); + struct iso9660_file_handle *f = file->fd; + pmm_free(f->extents, f->extent_count * sizeof(struct iso9660_extent)); + pmm_free(f, sizeof(struct iso9660_file_handle)); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/limine-10.5.1/common/lib/config.c new/limine-10.6.0/common/lib/config.c --- old/limine-10.5.1/common/lib/config.c 2025-12-26 15:00:56.000000000 +0100 +++ new/limine-10.6.0/common/lib/config.c 2025-12-28 15:18:08.000000000 +0100 @@ -19,7 +19,6 @@ static bool config_get_entry_name(char *ret, size_t index, size_t limit); static char *config_get_entry(size_t *size, size_t index); -static char *copy_config_value(const char *src); #define SEPARATOR '\n' @@ -322,7 +321,7 @@ char *comment = config_get_value(entry->body, 0, "COMMENT"); if (comment != NULL) { - entry->comment = copy_config_value(comment); + entry->comment = strdup(comment); } if (prev != NULL) @@ -649,30 +648,42 @@ static const char *lastkey; -static char *copy_config_value(const char *src) { - if (src == NULL) { - return NULL; - } - size_t len = strlen(src) + 1; - char *dst = ext_mem_alloc(len); - memcpy(dst, src, len); - return dst; -} - struct conf_tuple config_get_tuple(const char *config, size_t index, const char *key1, const char *key2) { + // Static buffers for return values. + // Callers must copy the result if they need persistence across calls. + #define CONF_TUPLE_BUF_SIZE 4096 + static char value1_buf[CONF_TUPLE_BUF_SIZE]; + static char value2_buf[CONF_TUPLE_BUF_SIZE]; + struct conf_tuple conf_tuple; char *tmp = config_get_value(config, index, key1); if (tmp == NULL) { return (struct conf_tuple){0}; } - conf_tuple.value1 = copy_config_value(tmp); + size_t len = strlen(tmp); + if (len >= CONF_TUPLE_BUF_SIZE) { + len = CONF_TUPLE_BUF_SIZE - 1; + } + memcpy(value1_buf, tmp, len); + value1_buf[len] = '\0'; + conf_tuple.value1 = value1_buf; const char *lk1 = lastkey; tmp = config_get_value(lk1, 0, key2); - conf_tuple.value2 = copy_config_value(tmp); + if (tmp != NULL) { + len = strlen(tmp); + if (len >= CONF_TUPLE_BUF_SIZE) { + len = CONF_TUPLE_BUF_SIZE - 1; + } + memcpy(value2_buf, tmp, len); + value2_buf[len] = '\0'; + conf_tuple.value2 = value2_buf; + } else { + conf_tuple.value2 = NULL; + } const char *lk2 = lastkey; @@ -682,7 +693,6 @@ if (conf_tuple.value2 != NULL && next_value1 != NULL) { if ((uintptr_t)lk2 > (uintptr_t)lk3) { - pmm_free(conf_tuple.value2, strlen(conf_tuple.value2) + 1); conf_tuple.value2 = NULL; } } @@ -690,12 +700,12 @@ return conf_tuple; } -// Static buffer for config_get_value return values. -// Callers must copy the result if they need persistence across calls. -#define CONFIG_VALUE_BUF_SIZE 4096 -static char config_value_buf[CONFIG_VALUE_BUF_SIZE]; - char *config_get_value(const char *config, size_t index, const char *key) { + // Static buffer for return values. + // Callers must copy the result if they need persistence across calls. + #define CONFIG_VALUE_BUF_SIZE 4096 + static char buf[CONFIG_VALUE_BUF_SIZE]; + if (!key || !config_ready) return NULL; @@ -721,10 +731,10 @@ if (value_len >= CONFIG_VALUE_BUF_SIZE) { value_len = CONFIG_VALUE_BUF_SIZE - 1; } - memcpy(config_value_buf, config + i, value_len); - config_value_buf[value_len] = '\0'; + memcpy(buf, config + i, value_len); + buf[value_len] = '\0'; lastkey = config + i; - return config_value_buf; + return buf; } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/limine-10.5.1/common/lib/elf.c new/limine-10.6.0/common/lib/elf.c --- old/limine-10.5.1/common/lib/elf.c 2025-12-26 15:00:56.000000000 +0100 +++ new/limine-10.6.0/common/lib/elf.c 2025-12-28 15:18:08.000000000 +0100 @@ -910,7 +910,8 @@ } // Validate p_offset + p_filesz doesn't overflow - if (phdr->p_offset > UINT64_MAX - phdr->p_filesz) { + uint64_t offset_end; + if (__builtin_add_overflow(phdr->p_offset, phdr->p_filesz, &offset_end)) { panic(true, "elf: p_offset + p_filesz overflow"); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/limine-10.5.1/common/lib/gterm.c new/limine-10.6.0/common/lib/gterm.c --- old/limine-10.5.1/common/lib/gterm.c 2025-12-26 15:00:56.000000000 +0100 +++ new/limine-10.6.0/common/lib/gterm.c 2025-12-28 15:18:08.000000000 +0100 @@ -665,6 +665,8 @@ char *menu_font_size = config_get_value(config, 0, "TERM_FONT_SIZE"); if (menu_font_size != NULL) { parse_resolution(&tmp_font_width, &tmp_font_height, NULL, menu_font_size); + // XXX: Do not allow widths != 8 + tmp_font_width = 8; size_t tmp_font_size = (tmp_font_width * tmp_font_height * FLANTERM_FB_FONT_GLYPHS) / 8; @@ -682,6 +684,11 @@ if ((f = uri_open(menu_font)) == NULL) { print("menu: Could not open font file.\n"); } else { + if (font_size > f->size) { + print("Font size too large for provided font file. Not loading.\n"); + fclose(f); + goto no_load_font; + } fread(f, font, 0, font_size); if (menu_font_size != NULL) { font_width = tmp_font_width; @@ -763,8 +770,8 @@ fb->framebuffer_height = tmp; } - terms[terms_i] = flanterm_fb_init(ext_mem_alloc, - pmm_free, + terms[terms_i] = flanterm_fb_init(ext_mem_alloc_size_t, + pmm_free_size_t, (void *)(uintptr_t)fb->framebuffer_addr, fb->framebuffer_width, fb->framebuffer_height, fb->framebuffer_pitch, fb->red_mask_size, fb->red_mask_shift, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/limine-10.5.1/common/lib/libc.c new/limine-10.6.0/common/lib/libc.c --- old/limine-10.5.1/common/lib/libc.c 2025-12-26 15:00:56.000000000 +0100 +++ new/limine-10.6.0/common/lib/libc.c 2025-12-28 15:18:08.000000000 +0100 @@ -5,6 +5,7 @@ #include <string.h> #include <lib/libc.h> #include <lib/misc.h> +#include <mm/pmm.h> // Slightly adapted strtoul() implementation from FreeBSD. // https://github.com/freebsd/freebsd-src/blob/de1aa3dab23c06fec962a14da3e7b4755c5880cf/lib/libc/stdlib/strtoul.c @@ -121,3 +122,10 @@ return p; } + +char *strdup(const char *s) { + size_t len = strlen(s) + 1; + char *buf = ext_mem_alloc(len); + memcpy(buf, s, len); + return buf; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/limine-10.5.1/common/lib/libc.h new/limine-10.6.0/common/lib/libc.h --- old/limine-10.5.1/common/lib/libc.h 2025-12-26 15:00:56.000000000 +0100 +++ new/limine-10.6.0/common/lib/libc.h 2025-12-28 15:18:08.000000000 +0100 @@ -31,5 +31,6 @@ int strncmp(const char *, const char *, size_t); int strncasecmp(const char *, const char *, size_t); int inet_pton(const char *src, void *dst); +char *strdup(const char *); #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/limine-10.5.1/common/lib/part.s2.c new/limine-10.6.0/common/lib/part.s2.c --- old/limine-10.5.1/common/lib/part.s2.c 2025-12-26 15:00:56.000000000 +0100 +++ new/limine-10.6.0/common/lib/part.s2.c 2025-12-28 15:18:08.000000000 +0100 @@ -39,10 +39,10 @@ if (__builtin_mul_overflow(block, volume->fastest_xfer_size, &block_offset)) { return false; } - if (first_sect > UINT64_MAX - block_offset) { + uint64_t read_sector; + if (__builtin_add_overflow(first_sect, block_offset, &read_sector)) { return false; } - uint64_t read_sector = first_sect + block_offset; for (;;) { int ret = disk_read_sectors(volume, volume->cache, @@ -74,12 +74,14 @@ panic(false, "Attempted volume_read() on pxe"); } - uint64_t part_size; - if (__builtin_mul_overflow(volume->sect_count, volume->sector_size, &part_size)) { - return false; - } - if (loc >= part_size || count > part_size - loc) { - return false; + if (volume->sect_count != (uint64_t)-1) { + uint64_t part_size; + if (__builtin_mul_overflow(volume->sect_count, volume->sector_size, &part_size)) { + return false; + } + if (loc >= part_size || count > part_size - loc) { + return false; + } } uint64_t block_size; @@ -223,10 +225,9 @@ } // Use actual entry size from header for offset calculation uint64_t partition_offset = (uint64_t)partition * entry_size; - if (entry_offset > UINT64_MAX - partition_offset) { + if (__builtin_add_overflow(entry_offset, partition_offset, &entry_offset)) { return INVALID_TABLE; // Addition overflow would occur } - entry_offset += partition_offset; struct gpt_entry entry = {0}; volume_read(volume, &entry, entry_offset, sizeof(entry)); @@ -415,7 +416,8 @@ if (__builtin_add_overflow(first_sect_64, (uint64_t)entry.first_sect, &first_sect_64)) { return NO_PARTITION; // Addition overflow } - if (first_sect_64 > UINT64_MAX - entry.sect_count) { + uint64_t partition_end; + if (__builtin_add_overflow(first_sect_64, (uint64_t)entry.sect_count, &partition_end)) { return NO_PARTITION; // Partition would overflow } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/limine-10.5.1/common/lib/term.c new/limine-10.6.0/common/lib/term.c --- old/limine-10.5.1/common/lib/term.c 2025-12-26 15:00:56.000000000 +0100 +++ new/limine-10.6.0/common/lib/term.c 2025-12-28 15:18:08.000000000 +0100 @@ -22,7 +22,7 @@ for (size_t i = 0; i < terms_i; i++) { struct flanterm_context *term = terms[i]; - term->deinit(term, pmm_free); + term->deinit(term, pmm_free_size_t); } pmm_free(terms, terms_i * sizeof(void *)); @@ -283,7 +283,7 @@ goto fail; } - terms[0] = flanterm_fb_init(ext_mem_alloc, pmm_free, + terms[0] = flanterm_fb_init(ext_mem_alloc_size_t, pmm_free_size_t, (void *)(uintptr_t)fb_fbs[0].framebuffer_addr, fb_fbs[0].framebuffer_width, fb_fbs[0].framebuffer_height, fb_fbs[0].framebuffer_pitch, fb_fbs[0].red_mask_size, fb_fbs[0].red_mask_shift, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/limine-10.5.1/common/lib/uri.c new/limine-10.6.0/common/lib/uri.c --- old/limine-10.5.1/common/lib/uri.c 2025-12-26 15:00:56.000000000 +0100 +++ new/limine-10.6.0/common/lib/uri.c 2025-12-28 15:18:08.000000000 +0100 @@ -14,10 +14,17 @@ #include <crypt/blake2b.h> // A URI takes the form of: resource(root):/path#hash -// The following function splits up a URI into its components +// The following function splits up a URI into its components. +// Note: Returns pointers into a static buffer. Callers must copy values +// if they need to persist across multiple uri_resolve() calls. bool uri_resolve(char *uri, char **resource, char **root, char **path, char **hash) { + #define URI_BUF_SIZE 4096 + static char buf[URI_BUF_SIZE]; + size_t length = strlen(uri) + 1; - char *buf = ext_mem_alloc(length); + if (length > URI_BUF_SIZE) { + panic(true, "uri_resolve: URI too long (max %u)", URI_BUF_SIZE - 1); + } memcpy(buf, uri, length); uri = buf; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/limine-10.5.1/common/mm/pmm.h new/limine-10.6.0/common/mm/pmm.h --- old/limine-10.5.1/common/mm/pmm.h 2025-12-26 15:00:56.000000000 +0100 +++ new/limine-10.6.0/common/mm/pmm.h 2025-12-28 15:18:08.000000000 +0100 @@ -55,15 +55,17 @@ bool memmap_alloc_range(uint64_t base, uint64_t length, uint32_t type, uint32_t overlay_type, bool panic, bool simulation, bool new_entry); void pmm_randomise_memory(void); -void *ext_mem_alloc(size_t count); -void *ext_mem_alloc_type(size_t count, uint32_t type); -void *ext_mem_alloc_type_aligned(size_t count, uint32_t type, size_t alignment); -void *ext_mem_alloc_type_aligned_mode(size_t count, uint32_t type, size_t alignment, bool allow_high_allocs); +void *ext_mem_alloc_size_t(size_t count); +void *ext_mem_alloc(uint64_t count); +void *ext_mem_alloc_type(uint64_t count, uint32_t type); +void *ext_mem_alloc_type_aligned(uint64_t count, uint32_t type, size_t alignment); +void *ext_mem_alloc_type_aligned_mode(uint64_t count, uint32_t type, size_t alignment, bool allow_high_allocs); -void *conv_mem_alloc(size_t count); +void *conv_mem_alloc(uint64_t count); -void pmm_free(void *ptr, size_t length); -void *pmm_realloc(void *old_ptr, size_t old_size, size_t new_size); +void pmm_free_size_t(void *ptr, size_t length); +void pmm_free(void *ptr, uint64_t length); +void *pmm_realloc(void *old_ptr, uint64_t old_size, uint64_t new_size); #if defined (UEFI) void pmm_release_uefi_mem(void); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/limine-10.5.1/common/mm/pmm.s2.c new/limine-10.6.0/common/mm/pmm.s2.c --- old/limine-10.5.1/common/mm/pmm.s2.c 2025-12-26 15:00:56.000000000 +0100 +++ new/limine-10.6.0/common/mm/pmm.s2.c 2025-12-28 15:18:08.000000000 +0100 @@ -19,7 +19,7 @@ bool allocations_disallowed = true; -void *conv_mem_alloc(size_t count) { +void *conv_mem_alloc(uint64_t count) { static uint64_t base = 4096; if (allocations_disallowed) @@ -564,14 +564,18 @@ } #endif -void pmm_free(void *ptr, size_t count) { +void pmm_free_size_t(void *ptr, size_t length) { + pmm_free(ptr, length); +} + +void pmm_free(void *ptr, uint64_t count) { count = ALIGN_UP(count, 4096); if (allocations_disallowed) panic(false, "Memory allocations disallowed"); memmap_alloc_range((uintptr_t)ptr, count, MEMMAP_USABLE, 0, false, false, true); } -void *pmm_realloc(void *old_ptr, size_t old_size, size_t new_size) { +void *pmm_realloc(void *old_ptr, uint64_t old_size, uint64_t new_size) { if (new_size == 0) { if (old_ptr != NULL) { pmm_free(old_ptr, old_size); @@ -591,20 +595,24 @@ return new_ptr; } -void *ext_mem_alloc(size_t count) { +void *ext_mem_alloc_size_t(size_t count) { + return ext_mem_alloc(count); +} + +void *ext_mem_alloc(uint64_t count) { return ext_mem_alloc_type(count, MEMMAP_BOOTLOADER_RECLAIMABLE); } -void *ext_mem_alloc_type(size_t count, uint32_t type) { +void *ext_mem_alloc_type(uint64_t count, uint32_t type) { return ext_mem_alloc_type_aligned(count, type, 4096); } -void *ext_mem_alloc_type_aligned(size_t count, uint32_t type, size_t alignment) { +void *ext_mem_alloc_type_aligned(uint64_t count, uint32_t type, size_t alignment) { return ext_mem_alloc_type_aligned_mode(count, type, alignment, false); } // Allocate memory top down. -void *ext_mem_alloc_type_aligned_mode(size_t count, uint32_t type, size_t alignment, bool allow_high_allocs) { +void *ext_mem_alloc_type_aligned_mode(uint64_t count, uint32_t type, size_t alignment, bool allow_high_allocs) { #if !defined (__x86_64__) && !defined (__i386__) (void)allow_high_allocs; #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/limine-10.5.1/common/protos/limine.c new/limine-10.6.0/common/protos/limine.c --- old/limine-10.5.1/common/protos/limine.c 2025-12-26 15:00:56.000000000 +0100 +++ new/limine-10.6.0/common/protos/limine.c 2025-12-28 15:18:08.000000000 +0100 @@ -1186,20 +1186,22 @@ module_required = internal_module->flags & LIMINE_INTERNAL_MODULE_REQUIRED; } else { - struct conf_tuple conf_tuple = - config_get_tuple(config, i - (module_request->revision >= 1 ? module_request->internal_module_count : 0), - "MODULE_PATH", "MODULE_STRING"); + size_t config_index = i - (module_request->revision >= 1 ? module_request->internal_module_count : 0); - struct conf_tuple conf_tuple1 = - config_get_tuple(config, i - (module_request->revision >= 1 ? module_request->internal_module_count : 0), - "MODULE_PATH", "MODULE_CMDLINE"); + // Try MODULE_STRING first, then fall back to MODULE_CMDLINE + struct conf_tuple conf_tuple = + config_get_tuple(config, config_index, "MODULE_PATH", "MODULE_STRING"); module_path = conf_tuple.value1; - module_cmdline = conf_tuple.value2 ?: conf_tuple1.value2; - } + module_cmdline = conf_tuple.value2; + + if (module_cmdline == NULL) { + conf_tuple = config_get_tuple(config, config_index, "MODULE_PATH", "MODULE_CMDLINE"); + module_cmdline = conf_tuple.value2; + } - if (module_cmdline == NULL) { - module_cmdline = ""; + // Copy cmdline since conf_tuple uses static buffers + module_cmdline = module_cmdline ? strdup(module_cmdline) : ""; } print("limine: Loading module `%#`...\n", module_path); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/limine-10.5.1/configure new/limine-10.6.0/configure --- old/limine-10.5.1/configure 2025-12-26 15:01:00.000000000 +0100 +++ new/limine-10.6.0/configure 2025-12-28 15:18:12.000000000 +0100 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.72 for Limine 10.5.1. +# Generated by GNU Autoconf 2.72 for Limine 10.6.0. # # Report bugs to <https://codeberg.org/Limine/Limine/issues>. # @@ -604,8 +604,8 @@ # Identity of this package. PACKAGE_NAME='Limine' PACKAGE_TARNAME='limine' -PACKAGE_VERSION='10.5.1' -PACKAGE_STRING='Limine 10.5.1' +PACKAGE_VERSION='10.6.0' +PACKAGE_STRING='Limine 10.6.0' PACKAGE_BUGREPORT='https://codeberg.org/Limine/Limine/issues' PACKAGE_URL='https://limine-bootloader.org/' @@ -1324,7 +1324,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -'configure' configures Limine 10.5.1 to adapt to many kinds of systems. +'configure' configures Limine 10.6.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1390,7 +1390,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of Limine 10.5.1:";; + short | recursive ) echo "Configuration of Limine 10.6.0:";; esac cat <<\_ACEOF @@ -1509,7 +1509,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -Limine configure 10.5.1 +Limine configure 10.6.0 generated by GNU Autoconf 2.72 Copyright (C) 2023 Free Software Foundation, Inc. @@ -1621,7 +1621,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by Limine $as_me 10.5.1, which was +It was created by Limine $as_me 10.6.0, which was generated by GNU Autoconf 2.72. Invocation command line was $ $0$ac_configure_args_raw @@ -6334,7 +6334,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by Limine $as_me 10.5.1, which was +This file was extended by Limine $as_me 10.6.0, which was generated by GNU Autoconf 2.72. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -6390,7 +6390,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -Limine config.status 10.5.1 +Limine config.status 10.6.0 configured by $0, generated by GNU Autoconf 2.72, with options \\"\$ac_cs_config\\" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/limine-10.5.1/timestamps new/limine-10.6.0/timestamps --- old/limine-10.5.1/timestamps 2025-12-26 15:00:58.000000000 +0100 +++ new/limine-10.6.0/timestamps 2025-12-28 15:18:09.000000000 +0100 @@ -1,3 +1,3 @@ REGEN_DATE="December 2025" -SOURCE_DATE_EPOCH="1766756882" -SOURCE_DATE_EPOCH_TOUCH="202512261448" +SOURCE_DATE_EPOCH="1766930472" +SOURCE_DATE_EPOCH_TOUCH="202512281501" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/limine-10.5.1/version new/limine-10.6.0/version --- old/limine-10.5.1/version 2025-12-26 15:01:00.000000000 +0100 +++ new/limine-10.6.0/version 2025-12-28 15:18:12.000000000 +0100 @@ -1 +1 @@ -10.5.1 +10.6.0
