Zig: basic_string::_M_construct null not valid on test

Created on 1 Dec 2019  ·  4Comments  ·  Source: ziglang/zig

Hi, I've written a precise 62 LOC of Zig in my lifetime and thus this is probably just me being a doof (in which case, this is an extremely unhelpful error).

I've written this code:

const std = @import("std");

fn parseDecimal(comptime T: type, text: []const u8) !T {
    var x: T = 0;

    for (text) |char| {
        const digit = try charToDigit(char);
        if (@mulWithOverflow(T, x, 10, &x)) {
            return error.Overflow;
        }
        if (@addWithOverflow(T, x, digit, &x)) {
            return error.Overflow;
        }
    }

    return x;
}

fn charToDigit(char: u8) !u4 {
    return switch (char) {
        '0'...'9' => @intCast(u4, char - '0'),
        else => error.InvalidChar,
    };
}

test "parse numbers" {
    const lol = parseDecimal(u64, "6969696969") catch unreachable;
    std.debug.assert(lol == 6969696969);
    if (parseDecimal(i192, "test")) |n| {
        std.debug.panic("somehow got {}, expected error.Overflow", n);
    } else |e| switch (e) {
        error.Overflow => {},
        else => unreachable,
    }
}

Upon running it with zig test I get:

0 ~/W/a/a/z/day1 zig test src/main.zig
terminate called after throwing an instance of 'std::logic_error'
  what():  basic_string::_M_construct null not valid
fish: “zig test src/main.zig” terminated by signal SIGABRT (Abort)
134 # the numbers before paths are exit codes of last cmd
bug contributor friendly stage1 stage2 upstream

Most helpful comment

Reduction:

test "parse numbers" {
    {var v: u128 = 1; v *= 10;} // works
    {var v: u192 = 1; v *= 10;} // works
    {var v: u256 = 1; v *= 10;} // works
    {var v: u257 = 1; v *= 10;} // works

    {var v: i127 = 1; v *= 10;} // works
    {var v: i128 = 1; v *= 10;} // works
    {var v: i129 = 1; v *= 10;} // crashes
}

All 4 comments

Reduction:

test "parse numbers" {
    {var v: u128 = 1; v *= 10;} // works
    {var v: u192 = 1; v *= 10;} // works
    {var v: u256 = 1; v *= 10;} // works
    {var v: u257 = 1; v *= 10;} // works

    {var v: i127 = 1; v *= 10;} // works
    {var v: i128 = 1; v *= 10;} // works
    {var v: i129 = 1; v *= 10;} // crashes
}

Further reduction:

source_filename = "test"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"

; Function Attrs: nounwind readnone speculatable
declare { i129, i1 } @llvm.smul.with.overflow.i129(i129, i129) #3

; Function Attrs: nobuiltin nounwind
define internal fastcc i1 @"foo"() unnamed_addr #1  {
Entry:
  %v = alloca i129, align 16
  store i129 1, i129* %v, align 16
  %0 = load i129, i129* %v, align 16
  %1 = call { i129, i1 } @llvm.smul.with.overflow.i129(i129 %0, i129 10)
  %2 = extractvalue { i129, i1 } %1, 1
  ret i1 %2;
}

@andrewrk, looks like we've got another bug for our LLVM friends :)

Next step is to report an LLVM bug, which is a contributor friendly task.

@andrewrk In the mean time, is there a possibility of having a work-around to this, or potentially detect it in use and warn about it?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

andrewrk picture andrewrk  ·  3Comments

bheads picture bheads  ·  3Comments

jayschwa picture jayschwa  ·  3Comments

jorangreef picture jorangreef  ·  3Comments

jorangreef picture jorangreef  ·  3Comments