#Panic: Incorrect Alignment

1 messages · Page 1 of 1 (latest)

opaque imp
#

Hi, I've been learning zig for the last 2weeks and I'm writing a little memory library for stringref search etc, but I get an incorrect alignment panic message when running this in my dll. which kinda makes sense since the address would be 0x401003 which isn't aligned to u32. I tried using align(1), readInt, didn't work so I asked AI as a last resort and it didn't do much more, so I'd like to know how I can fix that?

here's my code :

pub const Address = struct {
    address: usize,

    pub inline fn init(addr: usize) Address {
        return .{ .address = addr };
    }

    pub inline fn absoluteOffset(self: *const Address, off: usize) !Address {
        const base = self.address +% off;
        if (base == 0)
            return MemError.InvalidAddress;

        const bytes: *align(1) const [4]u8 = @ptrFromInt(base);
        const address = std.mem.readInt(u32, bytes, .little);
        return Address.init(address);
    }

    pub inline fn relativeOffset(self: *const Address, off: usize) !Address {
        const base = self.address +% off;
        if (base == 0)
            return MemError.InvalidAddress;

        const displacement = @as(*const i32, @ptrFromInt(base)).*;
        return Address.init(base +% 4 +% @as(usize, @intCast(displacement)));
    }

    pub fn ptr(self: *const Address, comptime T: type) T {
        return @ptrFromInt(self.address);
    }

    pub inline fn get(self: *const Address) usize {
        return self.address;
    }
};

and the stringref search :

        pub fn string(self: Scanner, comptime str: []const u8, comptime utf16: bool, findFirst: bool) !Address {
            const textSection = try self.module.section(std.heap.page_allocator, ".text");
            const rdataSection = try self.module.section(std.heap.page_allocator, ".rdata");

            const scanBytes = textSection.start.?.ptr([*]const u8);

            var lastMatch: ?Address = null;

            var i: usize = 0;
            while (i < textSection.size) : (i += 1) {
                if (scanBytes[i] == @intFromEnum(Mnemonic.PUSH)) {
                    const stringAddress = try Address.init(@intFromPtr(&scanBytes[i])).absoluteOffset(1);

                    if (rdataSection.isInSection(stringAddress)) {
                        const stringType = if (utf16) [*:0]const u16 else [*:0]const u8;
                        const stringBytes = stringAddress.ptr(stringType);

                        const firstChar: u16 = stringBytes[0];
                        const isAsciiChar = firstChar <= 0x7F;

                        if (isAsciiChar) {
                            if (utf16) {
                                const lea = std.mem.span(@as([*:0]const u16, @ptrCast(stringBytes)));
                                if (std.mem.eql(u16, std.unicode.utf8ToUtf16LeStringLiteral(str), lea)) {
                                    const result = Address.init(@intFromPtr(&scanBytes[i]));
                                    if (findFirst) {
                                        return result;
                                    }
                                    lastMatch = result;
                                }
                            } else {
                                const lea = std.mem.span(@as([*:0]const u8, @ptrCast(stringBytes)));
                                if (std.mem.eql(u8, str, lea)) {
                                    const result = Address.init(@intFromPtr(&scanBytes[i]));
                                    if (findFirst) {
                                        return result;
                                    }
                                    lastMatch = result;
                                }
                            }
                        }
                    }
                }
            }

            if (lastMatch) |match| {
                return match;
            }

            return MemError.NoResult;
        }
#

for anyone worried about it being for cheats or whatever because apparently that's an issue on some communities like QEMU/KVM, this is for a game revival project and we need to inject dlls to fix some stuff to get the servers working amongst other things, here's the actual repo : https://github.com/LowRezStudio/Tempest

GitHub

Monorepo for Tempest including MarshalLib, the launcher, the API and the CLI - LowRezStudio/Tempest

#

the code I sent in this channel isn't in the repo yet, since I wanted to fix that issue before a push

#

Panic: Incorrect Alignment

shrewd tulip
#

can you share the panic message? the solution is probably very simple: Zig has the notion of alignment baked into its pointer types: a *const u32 ("a pointer to a constant unsigned 32 bit integer") is 4-byte aligned (in popular architectures) - an attempt to create such a point type with a misaligned address will invoke checked Illegal Behaviour.
to remedy the problem, you can either make sure that indeed you only ever pass in well-aligned addresses, or alternatively, create a *align(1) const u32, which is a pointer to an under-aligned constant u32

opaque imp
#

Hi, the panic message is as simple as that, which isn't that helpful, but with some nasty print debug I was able to figure out that it was coming from the @as(*const u32, @ptrFromInt(base)).* and doing @as(*align(1) const u32, @ptrFromInt(base)).* didn't fix anything either

#

this is injected into a wine process via a zig injector we also made, since I'm on macos and the game is only on windows I have to do that

#

the builds are debug too

shrewd tulip
#

also, unrelated to the issue itself - but all that use of inlines is incorrect: inline fns are to be used only when you require precise control of the number of stack frames used, to force comptime-ness propagation, or when you have a measured performance increase.

from the language reference:

Note that inline actually restricts what the compiler is allowed to do. This can harm binary size, compilation speed, and even runtime performance.

shrewd tulip
opaque imp
opaque imp
#

but I don't mind checking again

#

first is without align(1), second is with

#

so my bad, I probably didn't inject the proper dll when I check before

#

also most of those values are correct but some of those are really weird like 245, ca, 1ffffff