Last active
December 31, 2025 18:25
-
-
Save eamonburns/abcdc76fc9f97994939b87d550937f45 to your computer and use it in GitHub Desktop.
Minimal reproduction for a UBSan error in ReleaseSafe but not Debug optimize mode
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const std = @import("std"); | |
| pub fn build(b: *std.Build) void { | |
| const target = b.standardTargetOptions(.{}); | |
| const optimize = b.standardOptimizeOption(.{}); | |
| const disable_check = b.option(bool, "disable_check", "Add `-fno-sanitize=object-size` to C flags") orelse false; | |
| const exe = b.addExecutable(.{ | |
| .name = "ubsan_fail", | |
| .root_module = b.createModule(.{ | |
| .target = target, | |
| .optimize = optimize, | |
| }), | |
| }); | |
| const flags: []const []const u8 = if (disable_check) &.{"-fno-sanitize=object-size"} else &.{}; | |
| exe.linkLibC(); | |
| exe.addCSourceFiles(.{ .files = &.{"main.c"}, .flags = flags }); | |
| b.installArtifact(exe); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <stdalign.h> | |
| #include <stddef.h> | |
| #include <stdint.h> | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| typedef struct { | |
| double x; | |
| char y; | |
| char fam[]; | |
| } FlexArray; | |
| void create_struct(char *key, size_t key_len) | |
| { | |
| size_t offset = offsetof(FlexArray, fam); | |
| size_t alignment = alignof(FlexArray); | |
| size_t aligned_size = (offset + key_len + 1 + alignment - 1) / alignment * alignment; | |
| FlexArray *m = malloc(offset + key_len + 1); | |
| printf("offset=%zu, (key_len + 1)=%zu, allocated=%zu, size=%zu, alignment=%zu, aligned_size=%zu\n", | |
| offset, key_len + 1, offset + key_len + 1, sizeof(FlexArray), alignment, aligned_size); | |
| memcpy(m->fam, key, key_len); | |
| m->fam[key_len] = 0; | |
| printf(" (success)\n"); | |
| } | |
| int main(void) | |
| { | |
| char *key = "howdy, partner!"; | |
| size_t offset = offsetof(FlexArray, fam); | |
| printf("First let's loop over key sizes the compiler can't reason about:\n"); | |
| printf("======================================================================\n"); | |
| for (size_t key_len = 0; key_len < sizeof(FlexArray) - offset + 2; | |
| key_len++) { | |
| create_struct(key, key_len); | |
| } | |
| printf("\nNow let's try with a statically known size EQUAL TO the total size:\n"); | |
| printf("======================================================================\n"); | |
| create_struct(key, sizeof(FlexArray) - offset - 1); | |
| printf("\nNow let's try with a statically known size LESS THAN the total size:\n"); | |
| printf("======================================================================\n"); | |
| create_struct(key, sizeof(FlexArray) - offset - 2); | |
| return 0; | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is a minimal reproduction of an issue I had when building NeoVim with Zig (issue: neovim/neovim#37160).
The repro crashes in ReleaseSafe mode due to an illegal instruction (inserted by UBSan), but not in Debug mode.
(credit goes to @kylesower for creating the repro)
Commands
You can use the
-Ddisable_checkoption to disable the specific check that is failing.