<commit_before>#ifndef __arm__
#error BrainfuckJIT currently only supports ARM
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>

/* Buffer size settings, these influence the runtime memory footprint */
#define INPUT_BUFFER_SIZE 512
#define LOOP_STACK_SIZE 100
#define JIT_MEMORY_SIZE 30000

/* Function types for the RLE callback and the actual JIT function */
typedef int (*rle_callback_t)(unsigned char, unsigned int, void *);
typedef void (*jit_function_t)(void);

/* Structure for passing the code generation data to the RLE function */
typedef struct {
    unsigned int **code_memory_pointer;
    unsigned int **loop_stack;
    unsigned int loop_size;
    unsigned int loop_max_size;
} codegen_param_t;

/* Structure for passing flags to the runtime */
typedef struct {
    unsigned int verbose;
    unsigned int jit_memory_size;
    unsigned int loop_stack_size;
    char *input_file_string;
} runtime_flags_t;

/* Read all characters from a file and call the handle_char callback for every
   sequence of equal characters, effectively RLEing the input file */
int rle_read_file(FILE *file, rle_callback_t handle_char, void *param) {
    unsigned char *input_buffer;
    unsigned int read_length;
    unsigned char last_character, this_character;
    unsigned int last_count;
    unsigned int i;
    int return_value;

    /* Allocate a buffer for the input */
    input_buffer = malloc(INPUT_BUFFER_SIZE);

    /* Set up the RLE variables */
    last_character = '\0';
    last_count = 0;

    do {
        /* Read a max of INPUT_BUFFER_SIZE from the input file */
        read_length = fread(input_buffer, sizeof(unsigned char), INPUT_BUFFER_SIZE, file);
        /* Iterate over all characters that were read */
        for (i = 0; i < read_length; i++) {
            this_character = *(input_buffer + i);

            /* If the character is different from the last character, call the
               callback and set the new character */
            if (this_character != last_character) {
                return_value = handle_char(last_character, last_count, param);
                /* If the callback returned an error state stop reading */
                if (return_value != 0) {
                    free(input_buffer);
                    return return_value;
                }
                last_character = this_character;
                last_count = 1;
            } else {
                last_count++;
            }
        }
    } while (read_length != 0);
    /* Finish up final characters */
    if (last_count > 0) {
        return_value = handle_char(last_character, last_count, param);
        if (return_value != 0) {
            free(input_buffer);
            return return_value;
        }
    }

    /* Deallocate the input buffer */
    free(input_buffer);
    return 0;
}

/* Callback function for rle_read_file which will calculate the total number of instructions
   this program will take once compiled */
int rle_determine_code_length(unsigned char character, unsigned int count, void *param) {
    unsigned int *code_length = (unsigned int *) param;
    /* Add number of bytes to the parameter base on character and count */
    switch (character) {
        /* "+-><" can be repeated in the same instruction */
        case '+':
        case '-':
            *code_length += 1 * sizeof(unsigned int);
            break;
        case '>':
        case '<':
            *code_length += 2 * sizeof(unsigned int);
            break;
        /* "[].," need to be repeated for every character */
        case '[':
        case ']':
            *code_length += 2 * count * sizeof(unsigned int);
            break;
        case '.':
        case ',':
            *code_length += (4 + (2 * count)) * sizeof(unsigned int);
            break;
    }

    return 0;
}

/* Callback function for rle_read_file which will actually do the code generation on the file, 
   this function requires an instance of codegen_param_t as input parameter */
int rle_code_generate(unsigned char character, unsigned int count, void *param) {
    codegen_param_t *codegen_param = (codegen_param_t *) param;
    unsigned int **code_memory_pointer = codegen_param->code_memory_pointer;
    unsigned int *code_memory = *code_memory_pointer;
    unsigned int i;

    /* Add number of bytes to the parameter base on character and count */
    switch (character) {
        /* "+-><" can be repeated in the same instruction */
        case '+':
            *(code_memory + 0) = 0xe2800000 | (count & 0xff); /* add r0, r0, count */
            *code_memory_pointer += 1;
            break;
        case '-':
            *(code_memory + 0) = 0xe2400000 | (count & 0xff); /* sub r0, r0, count */
            *code_memory_pointer += 1;
            break;
        case '>':
            if (count > 0xfff) {
                printf("Move right count is too large (> 4095)\n");
                return 2;
            }
            *(code_memory + 0) = 0xe4c10000 | (count & 0xfff); /* strb r0, [r1], count */
            *(code_memory + 1) = 0xe5d10000; /* ldrb r0, [r1] */
            *code_memory_pointer += 2;
            break;
        case '<':
            if (count > 0xfff) {
                printf("Move left count is too large (> 4095)\n");
                return 2;
            }
            *(code_memory + 0) = 0xe4410000 | (count & 0xfff); /* strb r0, [r1], -count */
            *(code_memory + 1) = 0xe5d10000; /* ldrb r0, [r1] */
            *code_memory_pointer += 2;
            break;
        /* "[].," need to be repeated for every character */
        case '[':
            for (i = 0; i < count; i++) {
                *(code_memory + (i * 2) + 0) = 0xe31000ff; /* tst r0, #255 */
                *(code_memory + (i * 2) + 1) = 0x0a000000; /* beq offset */

                /* Save the memory address of the branch instruction on the stack, so we
                   can fix the offset when we find the closing bracket */
                if (codegen_param->loop_size >= codegen_param->loop_max_size) {
                    printf("Loop stack size exceeded, try running with a larger -l.\n");
                    return 3;
                }
                *(codegen_param->loop_stack + codegen_param->loop_size++) = (code_memory + (i * 2) + 1);
            }
            *code_memory_pointer += 2 * count;
            break;
        case ']':
            for (i = 0; i < count; i++) {
                unsigned int *back_addr, *cur_addr, back_offset, forward_offset;
                /* Get the location of the opening bracket for this closing bracket */
                if (codegen_param->loop_size == 0) {
                    printf("Closing a loop while there is no open loop.\n");
                    return 3;
                }
                back_addr = *(codegen_param->loop_stack + --codegen_param->loop_size);
                cur_addr = (code_memory + (i * 2) + 1);

                /* Determine the branching offsets for the two branch instructions of this bracket pair */
                back_offset = ((unsigned int) back_addr - (unsigned int) cur_addr - 4) >> 2;
                forward_offset = ((unsigned int) cur_addr - (unsigned int) back_addr - 4) >> 2;
                if (!(back_offset < 0x007fffff || back_offset > 0xff800000) && 
                    !(forward_offset < 0x007fffff || forward_offset > 0xff800000)) {
                    printf("Loop jump requires offset outside of the 32MB jump range.\n");
                    return 3;
                }

                *(code_memory + (i * 2) + 0) = 0xe31000ff; /* tst r0, #255 */
                *(code_memory + (i * 2) + 1) = 0x1a000000 | (back_offset & 0xffffff); /* bne offset */
                *((unsigned int *) back_addr) |= (forward_offset & 0xffffff);
            }
            *code_memory_pointer += 2 * count;
            break;
        case '.':
            *(code_memory + 0) = 0xe5c10000; /* strb r0, [r1] */
            *(code_memory + 1) = 0xe3a07004; /* mov r7, #4 */
            *(code_memory + 2) = 0xe3a02001; /* mov r2, #1 */
            for (i = 0; i < count; i++) {
                /* Run a systemcall write(stdout, jit_memory[current_cell], 1) */
                *(code_memory + 3 + (i * 2) + 0) = 0xe3a00001; /* mov r0, #1 */
                *(code_memory + 3 + (i * 2) + 1) = 0xef000000; /* svc #0 */
            }
            *(code_memory + 3 + (i * 2) + 0) = 0xe5d10000; /* ldrb r0, [r1] */
            *code_memory_pointer += 4 + (2 * count);
            break;
        case ',':
            *(code_memory + 0) = 0xe5c10000; /* strb r0, [r1] */
            *(code_memory + 1) = 0xe3a07003; /* mov r7, #3 */
            *(code_memory + 2) = 0xe3a02001; /* mov r2, #1 */
            for (i = 0; i < count; i++) {
                /* Run a systemcall read(stdin, jit_memory[current_cell], 1) */<commit_msg>Make branch address bounds check more robust<commit_after>#ifndef __arm__
#error BrainfuckJIT currently only supports ARM
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>

/* Buffer size settings, these influence the runtime memory footprint */
#define INPUT_BUFFER_SIZE 512
#define LOOP_STACK_SIZE 100
#define JIT_MEMORY_SIZE 30000

/* Function types for the RLE callback and the actual JIT function */
typedef int (*rle_callback_t)(unsigned char, unsigned int, void *);
typedef void (*jit_function_t)(void);

/* Structure for passing the code generation data to the RLE function */
typedef struct {
    unsigned int **code_memory_pointer;
    unsigned int **loop_stack;
    unsigned int loop_size;
    unsigned int loop_max_size;
} codegen_param_t;

/* Structure for passing flags to the runtime */
typedef struct {
    unsigned int verbose;
    unsigned int jit_memory_size;
    unsigned int loop_stack_size;
    char *input_file_string;
} runtime_flags_t;

/* Read all characters from a file and call the handle_char callback for every
   sequence of equal characters, effectively RLEing the input file */
int rle_read_file(FILE *file, rle_callback_t handle_char, void *param) {
    unsigned char *input_buffer;
    unsigned int read_length;
    unsigned char last_character, this_character;
    unsigned int last_count;
    unsigned int i;
    int return_value;

    /* Allocate a buffer for the input */
    input_buffer = malloc(INPUT_BUFFER_SIZE);

    /* Set up the RLE variables */
    last_character = '\0';
    last_count = 0;

    do {
        /* Read a max of INPUT_BUFFER_SIZE from the input file */
        read_length = fread(input_buffer, sizeof(unsigned char), INPUT_BUFFER_SIZE, file);
        /* Iterate over all characters that were read */
        for (i = 0; i < read_length; i++) {
            this_character = *(input_buffer + i);

            /* If the character is different from the last character, call the
               callback and set the new character */
            if (this_character != last_character) {
                return_value = handle_char(last_character, last_count, param);
                /* If the callback returned an error state stop reading */
                if (return_value != 0) {
                    free(input_buffer);
                    return return_value;
                }
                last_character = this_character;
                last_count = 1;
            } else {
                last_count++;
            }
        }
    } while (read_length != 0);
    /* Finish up final characters */
    if (last_count > 0) {
        return_value = handle_char(last_character, last_count, param);
        if (return_value != 0) {
            free(input_buffer);
            return return_value;
        }
    }

    /* Deallocate the input buffer */
    free(input_buffer);
    return 0;
}

/* Callback function for rle_read_file which will calculate the total number of instructions
   this program will take once compiled */
int rle_determine_code_length(unsigned char character, unsigned int count, void *param) {
    unsigned int *code_length = (unsigned int *) param;
    /* Add number of bytes to the parameter base on character and count */
    switch (character) {
        /* "+-><" can be repeated in the same instruction */
        case '+':
        case '-':
            *code_length += 1 * sizeof(unsigned int);
            break;
        case '>':
        case '<':
            *code_length += 2 * sizeof(unsigned int);
            break;
        /* "[].," need to be repeated for every character */
        case '[':
        case ']':
            *code_length += 2 * count * sizeof(unsigned int);
            break;
        case '.':
        case ',':
            *code_length += (4 + (2 * count)) * sizeof(unsigned int);
            break;
    }

    return 0;
}

/* Callback function for rle_read_file which will actually do the code generation on the file, 
   this function requires an instance of codegen_param_t as input parameter */
int rle_code_generate(unsigned char character, unsigned int count, void *param) {
    codegen_param_t *codegen_param = (codegen_param_t *) param;
    unsigned int **code_memory_pointer = codegen_param->code_memory_pointer;
    unsigned int *code_memory = *code_memory_pointer;
    unsigned int i;

    /* Add number of bytes to the parameter base on character and count */
    switch (character) {
        /* "+-><" can be repeated in the same instruction */
        case '+':
            *(code_memory + 0) = 0xe2800000 | (count & 0xff); /* add r0, r0, count */
            *code_memory_pointer += 1;
            break;
        case '-':
            *(code_memory + 0) = 0xe2400000 | (count & 0xff); /* sub r0, r0, count */
            *code_memory_pointer += 1;
            break;
        case '>':
            if (count > 0xfff) {
                printf("Move right count is too large (> 4095)\n");
                return 2;
            }
            *(code_memory + 0) = 0xe4c10000 | (count & 0xfff); /* strb r0, [r1], count */
            *(code_memory + 1) = 0xe5d10000; /* ldrb r0, [r1] */
            *code_memory_pointer += 2;
            break;
        case '<':
            if (count > 0xfff) {
                printf("Move left count is too large (> 4095)\n");
                return 2;
            }
            *(code_memory + 0) = 0xe4410000 | (count & 0xfff); /* strb r0, [r1], -count */
            *(code_memory + 1) = 0xe5d10000; /* ldrb r0, [r1] */
            *code_memory_pointer += 2;
            break;
        /* "[].," need to be repeated for every character */
        case '[':
            for (i = 0; i < count; i++) {
                *(code_memory + (i * 2) + 0) = 0xe31000ff; /* tst r0, #255 */
                *(code_memory + (i * 2) + 1) = 0x0a000000; /* beq offset */

                /* Save the memory address of the branch instruction on the stack, so we
                   can fix the offset when we find the closing bracket */
                if (codegen_param->loop_size >= codegen_param->loop_max_size) {
                    printf("Loop stack size exceeded, try running with a larger -l.\n");
                    return 3;
                }
                *(codegen_param->loop_stack + codegen_param->loop_size++) = (code_memory + (i * 2) + 1);
            }
            *code_memory_pointer += 2 * count;
            break;
        case ']':
            for (i = 0; i < count; i++) {
                unsigned int *back_addr, *cur_addr;
                int back_offset, forward_offset;
                int back_in_range, forward_in_range;
                /* Get the location of the opening bracket for this closing bracket */
                if (codegen_param->loop_size == 0) {
                    printf("Closing a loop while there is no open loop.\n");
                    return 3;
                }
                back_addr = *(codegen_param->loop_stack + --codegen_param->loop_size);
                cur_addr = (code_memory + (i * 2) + 1);

                /* Determine the branching offsets for the two branch instructions of this bracket pair */
                back_offset = (int)((unsigned int) back_addr - (unsigned int) cur_addr - 4) >> 2;
                forward_offset = (int)((unsigned int) cur_addr - (unsigned int) back_addr - 4) >> 2;

                back_in_range = back_offset >= -0x800000 && back_offset <= 0x7fffff;
                forward_in_range = forward_offset >= -0x800000 && forward_offset <= 0x7fffff;
                if (!back_in_range || !forward_in_range) {
                    printf("Loop jump requires offset outside of the 32MB jump range.\n");
                    return 3;
                }

                *(code_memory + (i * 2) + 0) = 0xe31000ff; /* tst r0, #255 */
                *(code_memory + (i * 2) + 1) = 0x1a000000 | (back_offset & 0xffffff); /* bne offset */
                *((unsigned int *) back_addr) |= (forward_offset & 0xffffff);
            }
            *code_memory_pointer += 2 * count;
            break;
        case '.':
            *(code_memory + 0) = 0xe5c10000; /* strb r0, [r1] */
            *(code_memory + 1) = 0xe3a07004; /* mov r7, #4 */
            *(code_memory + 2) = 0xe3a02001; /* mov r2, #1 */
            for (i = 0; i < count; i++) {
                /* Run a systemcall write(stdout, jit_memory[current_cell], 1) */
                *(code_memory + 3 + (i * 2) + 0) = 0xe3a00001; /* mov r0, #1 */
                *(code_memory + 3 + (i * 2) + 1) = 0xef000000; /* svc #0 */
            }
            *(code_memory + 3 + (i * 2) + 0) = 0xe5d10000; /* ldrb r0, [r1] */
            *code_memory_pointer += 4 + (2 * count);
            break;
        case ',':
            *(code_memory + 0) = 0xe5c10000; /* strb r0, [r1] */
            *(code_memory + 1) = 0xe3a07003; /* mov r7, #3 */
            *(code_memory + 2) = 0xe3a02001; /* mov r2, #1 */
            for (i = 0; i < count; i++) {
                /* Run a systemcall read(stdin, jit_memory[current_cell], 1) */
{'fraction_non_alphanumeric': 0.11331476323119777, 'fraction_numerical': 0.03275766016713092, 'mean_word_length': 1.8967242213974504, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 61, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1471588', 'n_tokens_mistral': 5721, 'n_tokens_neox': 5153, 'n_words': 1650}