crabc 0.7.8

A Rust musl-compatible libc with a dynamic linker
/* Copyright (c) 2026 Meng Zhuo */
/* SPDX-License-Identifier: BSD-3-Clause */

#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>

#define THREADS 4
#define ITERS 50000

static void *worker(void *arg) {
    unsigned seed = (unsigned)(uintptr_t)arg;
    for (int i = 0; i < ITERS; i++) {
        size_t n = (size_t)((seed = seed * 1103515245u + 12345u) % 2048) + 1;
        unsigned char *p = malloc(n);
        if (!p) return (void *)1;
        memset(p, i & 0xff, n);
        if (p[0] != (unsigned char)(i & 0xff)) return (void *)2;
        if ((i & 3) == 0) {
            size_t nn = n + (seed % 512);
            p = realloc(p, nn);
            if (!p) return (void *)3;
            memset(p + n, 0x5a, nn - n);
        }
        free(p);
    }
    return 0;
}

int main(void) {
    enum { N = 5000 };
    static void *p[N];
    static size_t sz[N];

    for (int i = 0; i < N; i++) {
        sz[i] = (size_t)((i * 37) % 4096) + 1;
        p[i] = malloc(sz[i]);
        if (!p[i]) return 10;
        if (malloc_usable_size(p[i]) < sz[i]) return 11;
        memset(p[i], i & 0xff, sz[i]);
    }
    for (int i = 0; i < N; i++) {
        unsigned char *q = p[i];
        for (size_t j = 0; j < sz[i]; j++) {
            if (q[j] != (unsigned char)(i & 0xff)) return 12;
        }
        if (i & 1) {
            p[i] = realloc(p[i], sz[i] + 100);
            if (!p[i]) return 13;
            memset((char *)p[i] + sz[i], 0xaa, 100);
        }
    }
    for (int i = 0; i < N; i++) free(p[i]);

    for (int i = 0; i < 500; i++) {
        void *q = aligned_alloc(256, 1024);
        if (!q || ((uintptr_t)q & 255)) return 14;
        memset(q, 0x5a, 1024);
        free(q);
    }
    for (int i = 0; i < 500; i++) {
        void *q = NULL;
        if (posix_memalign(&q, 4096, 100)) return 15;
        if ((uintptr_t)q & 4095) return 16;
        free(q);
    }
    {
        void *q = valloc(300);
        if (!q || ((uintptr_t)q & 4095)) return 17;
        free(q);
    }

    pthread_t t[THREADS];
    for (long i = 0; i < THREADS; i++) {
        if (pthread_create(&t[i], 0, worker, (void *)(i + 1))) return 18;
    }
    for (int i = 0; i < THREADS; i++) {
        void *r;
        if (pthread_join(t[i], &r) || r) return 19;
    }

    void *fork_ptr = malloc(1234);
    if (!fork_ptr) return 20;
    memset(fork_ptr, 0x33, 1234);
    pid_t pid = fork();
    if (pid == 0) {
        void *q = malloc(777);
        if (!q) _exit(21);
        memset(q, 0x44, 777);
        free(q);
        free(fork_ptr);
        _exit(0);
    }
    int st;
    if (pid < 0 || waitpid(pid, &st, 0) != pid) return 22;
    if (!WIFEXITED(st) || WEXITSTATUS(st)) return 23;
    free(fork_ptr);

    puts("allocator ok");
    return 0;
}