Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More crash fixes + update to fuzz build #691

Merged
merged 8 commits into from
Apr 23, 2024
35 changes: 5 additions & 30 deletions build.zig
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
const std = @import("std");
const Build = std.Build;
const GenerateDef = @import("build/GenerateDef.zig");
const ZigLibDirStep = @import("build/ZigLibDir.zig");

const aro_version = std.SemanticVersion{
.major = 0,
Expand All @@ -11,44 +10,20 @@ const aro_version = std.SemanticVersion{

fn addFuzzStep(b: *Build, target: std.Build.ResolvedTarget, afl_clang_lto_path: []const u8, aro_module: *std.Build.Module) !void {
const fuzz_step = b.step("fuzz", "Build executable for fuzz testing.");
const fuzz_target = blk: {
var query = target.query;
query.ofmt = .c;
break :blk b.resolveTargetQuery(query);
};

const lib_dir_step = try ZigLibDirStep.create(b);

const compiler_rt = b.createModule(.{
.root_source_file = lib_dir_step.getCompilerRTPath(),
});
const fuzz_lib = b.addStaticLibrary(.{
.name = "fuzz-lib",
.root_source_file = .{ .path = "test/fuzz/fuzz_lib.zig" },
.optimize = .Debug,
.target = fuzz_target,
.target = target,
.single_threaded = true,
});
fuzz_lib.root_module.addImport("compiler_rt", compiler_rt);
fuzz_lib.want_lto = true;
fuzz_lib.bundle_compiler_rt = true;
fuzz_lib.pie = true;

fuzz_lib.root_module.addImport("aro", aro_module);
const fuzz_compile = b.addSystemCommand(&.{
afl_clang_lto_path,
"-Wno-incompatible-pointer-types",
"-nostdinc",
"-isystem",
});
fuzz_compile.addDirectoryArg(lib_dir_step.getIncludePath());
fuzz_compile.addArgs(&.{
"-isystem",
"/usr/include",
"-isystem",
"/usr/local/include",
"-std=c99",
});
const fuzz_compile = b.addSystemCommand(&.{afl_clang_lto_path});
fuzz_compile.addFileArg(.{ .path = "test/fuzz/main.c" });
fuzz_compile.addArg("-I");
fuzz_compile.addDirectoryArg(lib_dir_step.getLibPath());
fuzz_compile.addArg("-o");
const fuzz_exe = fuzz_compile.addOutputFileArg("arofuzz");
const fuzz_install = b.addInstallBinFile(fuzz_exe, "arofuzz");
Expand Down
65 changes: 0 additions & 65 deletions build/ZigLibDir.zig

This file was deleted.

25 changes: 16 additions & 9 deletions src/aro/Parser.zig
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ value_map: Tree.ValueMap,

// buffers used during compilation
syms: SymbolStack = .{},
strings: std.ArrayList(u8),
strings: std.ArrayListAligned(u8, 4),
labels: std.ArrayList(Label),
list_buf: NodeList,
decl_buf: NodeList,
Expand Down Expand Up @@ -160,7 +160,7 @@ record: struct {
}

fn addFieldsFromAnonymous(r: @This(), p: *Parser, ty: Type) Error!void {
for (ty.data.record.fields) |f| {
for (ty.getRecord().?.fields) |f| {
if (f.isAnonymousRecord()) {
try r.addFieldsFromAnonymous(p, f.ty.canonicalize(.standard));
} else if (f.name_tok != 0) {
Expand Down Expand Up @@ -688,7 +688,7 @@ pub fn parse(pp: *Preprocessor) Compilation.Error!Tree {
.gpa = pp.comp.gpa,
.arena = arena.allocator(),
.tok_ids = pp.tokens.items(.id),
.strings = std.ArrayList(u8).init(pp.comp.gpa),
.strings = std.ArrayListAligned(u8, 4).init(pp.comp.gpa),
.value_map = Tree.ValueMap.init(pp.comp.gpa),
.data = NodeList.init(pp.comp.gpa),
.labels = std.ArrayList(Label).init(pp.comp.gpa),
Expand Down Expand Up @@ -5466,10 +5466,14 @@ pub const Result = struct {

fn lvalConversion(res: *Result, p: *Parser) Error!void {
if (res.ty.isFunc()) {
const elem_ty = try p.arena.create(Type);
elem_ty.* = res.ty;
res.ty.specifier = .pointer;
res.ty.data = .{ .sub_type = elem_ty };
if (res.ty.isInvalidFunc()) {
res.ty = .{ .specifier = .invalid };
} else {
const elem_ty = try p.arena.create(Type);
elem_ty.* = res.ty;
res.ty.specifier = .pointer;
res.ty.data = .{ .sub_type = elem_ty };
}
try res.implicitCast(p, .function_to_pointer);
} else if (res.ty.isArray()) {
res.val = .{};
Expand Down Expand Up @@ -8018,6 +8022,9 @@ fn stringLiteral(p: *Parser) Error!Result {
const strings_top = p.strings.items.len;
defer p.strings.items.len = strings_top;

const literal_start = mem.alignForward(usize, strings_top, @intFromEnum(char_width));
try p.strings.resize(literal_start);

while (p.tok_i < string_end) : (p.tok_i += 1) {
const this_kind = text_literal.Kind.classify(p.tok_ids[p.tok_i], .string_literal).?;
const slice = this_kind.contentSlice(p.tokSlice(p.tok_i));
Expand Down Expand Up @@ -8068,7 +8075,7 @@ fn stringLiteral(p: *Parser) Error!Result {
switch (char_width) {
.@"1" => p.strings.appendSliceAssumeCapacity(view.bytes),
.@"2" => {
const capacity_slice: []align(@alignOf(u16)) u8 = @alignCast(p.strings.unusedCapacitySlice());
const capacity_slice: []align(@alignOf(u16)) u8 = @alignCast(p.strings.allocatedSlice()[literal_start..]);
const dest_len = std.mem.alignBackward(usize, capacity_slice.len, 2);
const dest = std.mem.bytesAsSlice(u16, capacity_slice[0..dest_len]);
const words_written = std.unicode.utf8ToUtf16Le(dest, view.bytes) catch unreachable;
Expand All @@ -8089,7 +8096,7 @@ fn stringLiteral(p: *Parser) Error!Result {
}
}
p.strings.appendNTimesAssumeCapacity(0, @intFromEnum(char_width));
const slice = p.strings.items[strings_top..];
const slice = p.strings.items[literal_start..];

// TODO this won't do anything if there is a cache hit
const interned_align = mem.alignForward(
Expand Down
2 changes: 1 addition & 1 deletion src/aro/Preprocessor.zig
Original file line number Diff line number Diff line change
Expand Up @@ -976,7 +976,7 @@ fn expr(pp: *Preprocessor, tokenizer: *Tokenizer) MacroError!bool {
.tok_i = @intCast(token_state.tokens_len),
.arena = pp.arena.allocator(),
.in_macro = true,
.strings = std.ArrayList(u8).init(pp.comp.gpa),
.strings = std.ArrayListAligned(u8, 4).init(pp.comp.gpa),

.data = undefined,
.value_map = undefined,
Expand Down
22 changes: 15 additions & 7 deletions src/aro/Type.zig
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,16 @@ pub fn params(ty: Type) []Func.Param {
};
}

/// Returns true if the return value or any param of `ty` is `.invalid`
/// Asserts that ty is a function type
pub fn isInvalidFunc(ty: Type) bool {
if (ty.returnType().is(.invalid)) return true;
for (ty.params()) |param| {
if (param.ty.is(.invalid)) return true;
}
return false;
}

pub fn arrayLen(ty: Type) ?u64 {
return switch (ty.specifier) {
.array, .static_array => ty.data.array.len,
Expand Down Expand Up @@ -1106,7 +1116,7 @@ pub fn alignof(ty: Type, comp: *const Compilation) u29 {
.ulong_long => comp.target.c_type_alignment(.ulonglong),

.bit_int => @min(
std.math.ceilPowerOfTwoPromote(u16, (ty.data.int.bits + 7) / 8),
std.math.ceilPowerOfTwoPromote(u16, (ty.data.int.bits +| 7) / 8),
comp.target.maxIntAlignment(),
),

Expand Down Expand Up @@ -1220,9 +1230,9 @@ pub fn eql(a_param: Type, b_param: Type, comp: *const Compilation, check_qualifi
if (!b.isFunc()) return false;
} else if (a.isArray()) {
if (!b.isArray()) return false;
} else if (a.specifier == .@"enum" and a.data.@"enum".fixed and b.specifier != .@"enum") {
} else if (a.specifier == .@"enum" and b.specifier != .@"enum") {
return a.data.@"enum".tag_ty.eql(b, comp, check_qualifiers);
} else if (b.specifier == .@"enum" and b.data.@"enum".fixed and a.specifier != .@"enum") {
} else if (b.specifier == .@"enum" and a.specifier != .@"enum") {
return a.eql(b.data.@"enum".tag_ty, comp, check_qualifiers);
} else if (a.specifier != b.specifier) return false;

Expand Down Expand Up @@ -1318,10 +1328,8 @@ pub fn integerRank(ty: Type, comp: *const Compilation) usize {
.typeof_expr => ty.data.expr.ty.integerRank(comp),
.attributed => ty.data.attributed.base.integerRank(comp),

.@"enum" => {
std.debug.assert(real.data.@"enum".fixed);
return real.data.@"enum".tag_ty.integerRank(comp);
},
.@"enum" => real.data.@"enum".tag_ty.integerRank(comp),

else => unreachable,
});
}
Expand Down
14 changes: 10 additions & 4 deletions src/aro/Value.zig
Original file line number Diff line number Diff line change
Expand Up @@ -757,10 +757,16 @@ pub fn bitAnd(lhs: Value, rhs: Value, comp: *Compilation) !Value {
const lhs_bigint = lhs.toBigInt(&lhs_space, comp);
const rhs_bigint = rhs.toBigInt(&rhs_space, comp);

const limbs = try comp.gpa.alloc(
std.math.big.Limb,
@max(lhs_bigint.limbs.len, rhs_bigint.limbs.len),
);
const limb_count = if (lhs_bigint.positive and rhs_bigint.positive)
@min(lhs_bigint.limbs.len, rhs_bigint.limbs.len)
else if (lhs_bigint.positive)
lhs_bigint.limbs.len
else if (rhs_bigint.positive)
rhs_bigint.limbs.len
else
@max(lhs_bigint.limbs.len, rhs_bigint.limbs.len) + 1;

const limbs = try comp.gpa.alloc(std.math.big.Limb, limb_count);
defer comp.gpa.free(limbs);
var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined };

Expand Down
1 change: 1 addition & 0 deletions test/cases/alignment.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ _Static_assert(_Alignof(n) == 32, "incorrect alignment");

__attribute__((aligned("foo"))) o;
_Alignas(1.2) p;
_Static_assert(_Alignof(_BitInt(65535)) > 0, "");

#define EXPECTED_ERRORS "alignment.c:1:1: error: '_Alignas' attribute only applies to variables and fields" \
"alignment.c:3:3: error: '_Alignas' attribute only applies to variables and fields" \
Expand Down
5 changes: 5 additions & 0 deletions test/cases/attributed anonymous record.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
struct A{
union {
char a;
} __attribute__((packed));
};
1 change: 1 addition & 0 deletions test/cases/binary expressions.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ _Static_assert(2.0||(2.0 == 2.0), "");
_Static_assert(2.0||(3.0 > 2.0), "");
_Static_assert(2.0||(2.0 && 2.0), "");

_Static_assert((-10 & -1) == -10, "");
#define EXPECTED_ERRORS "binary expressions.c:3:7: error: invalid operands to binary expression ('long' and 'float')" \
"binary expressions.c:6:13: error: invalid operands to binary expression ('char' and 'int *')" \
"binary expressions.c:8:9: error: invalid operands to binary expression ('void (*)(void)' and 'void')" \
Expand Down
18 changes: 18 additions & 0 deletions test/cases/enum pointer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
enum E {
A,
};

void foo(void) {
int x;
unsigned y;
enum E *p1 = &x;
enum E *p2 = &y;
}

#if __WIN32__
#define EXPECTED_ERRORS "enum pointer.c:9:18: warning: incompatible pointer types initializing 'enum E *' from incompatible type 'unsigned int *' converts between pointers to integer types with different sign [-Wpointer-sign]" \

#else
#define EXPECTED_ERRORS "enum pointer.c:8:18: warning: incompatible pointer types initializing 'enum E *' from incompatible type 'int *' [-Wincompatible-pointer-types]" \

#endif
4 changes: 4 additions & 0 deletions test/cases/functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ int (*return_array_ptr(void))[2] {
void no_params(void);
void no_params(int x){}

void invalid_func(__auto_type);
int invalid_int = invalid_func;

#define EXPECTED_ERRORS "functions.c:10:12: error: parameter named 'quux' is missing" \
"functions.c:20:14: error: illegal initializer (only variables can be initialized)" \
"functions.c:18:2: warning: non-void function 'foooo' does not return a value [-Wreturn-type]" \
Expand All @@ -90,4 +93,5 @@ void no_params(int x){}
"functions.c:55:9: error: parameter has incomplete type 'enum EE'" \
"functions.c:79:6: error: redefinition of 'no_params' with a different type" \
"functions.c:78:6: note: previous definition is here" \
"functions.c:81:19: error: '__auto_type' not allowed in function prototype" \

12 changes: 12 additions & 0 deletions test/cases/unaligned u16 string literal.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
struct S {
int x;
};

void foo(void) {
struct S s;
s.y;
}

_Static_assert(u"A");

#define NO_ERROR_VALIDATION
Loading