Repository: dotnet/runtime
File: src/tasks/AppleAppBuilder/Templates/runtime-coreclr.m (Objective-C)

Code before:
const void*
pinvoke_override (const char *libraryName, const char *entrypointName)
{
    if (!strcmp (libraryName, "__Internal"))
    {
        return dlsym (RTLD_DEFAULT, entrypointName);
    }

    return NULL;
}

#include <mach-o/dyld.h>
#include <mach-o/loader.h>
size_t get_image_size(void* base_address)
{
    uint32_t image_count = _dyld_image_count();
    for (uint32_t i = 0; i < image_count; ++i)
    {
        const struct mach_header_64* header = (const struct mach_header_64*)_dyld_get_image_header(i);
        if ((const void*)header != base_address)
            continue;

        const struct load_command* cmd = (const struct load_command*)((const char*)header + sizeof(struct mach_header_64));

        size_t image_size = 0;
        for (uint32_t j = 0; j < header->ncmds; ++j)
        {
            if (cmd->cmd == LC_SEGMENT_64)
            {
                const struct segment_command_64* seg = (const struct segment_command_64*)cmd;
                size_t end_addr = (size_t)(seg->vmaddr + seg->vmsize);
                if (end_addr > image_size)
                    image_size = end_addr;
            }

            cmd = (const struct load_command*)((const char*)cmd + cmd->cmdsize);
        }

        return image_size;
    }
}

bool get_native_code_data(const struct host_runtime_contract_native_code_context* context, struct host_runtime_contract_native_code_data* data)
{
    if (!context || !data || !context->assembly_path || !context->owner_composite_name)
        return false;

    // Look for the owner composite R2R image in the same directory as the assembly
    char r2r_path[PATH_MAX];
    const char *last_slash = strrchr(context->assembly_path, '/');
    size_t dir_len = last_slash ? (size_t)(last_slash - context->assembly_path) : 0;

Review comment (bug):
The `get_image_size` function should return 0 when the base address is not found in the loaded images. Currently, if no matching image is found after the loop completes, the function returns without an explicit value, which results in undefined behavior. Add `return 0;` after the loop.
```suggestion
    }
    return 0;
```

Code after:
    {
        return dlsym (RTLD_DEFAULT, entrypointName);
    }

    return NULL;
}

#include <mach-o/dyld.h>
#include <mach-o/loader.h>
size_t get_image_size(const struct mach_header_64* header)
{
    const struct load_command* cmd = (const struct load_command*)((const char*)header + sizeof(struct mach_header_64));

    size_t image_size = 0;
    for (uint32_t j = 0; j < header->ncmds; ++j)
    {
        if (cmd->cmd == LC_SEGMENT_64)
        {
            const struct segment_command_64* seg = (const struct segment_command_64*)cmd;
            size_t end_addr = (size_t)(seg->vmaddr + seg->vmsize);
            if (end_addr > image_size)
                image_size = end_addr;
        }

        cmd = (const struct load_command*)((const char*)cmd + cmd->cmdsize);
    }

    return image_size;
}

bool get_native_code_data(const struct host_runtime_contract_native_code_context* context, struct host_runtime_contract_native_code_data* data)
{
    if (!context || !data || !context->assembly_path || !context->owner_composite_name)
        return false;

    // Look for the owner composite R2R image in the same directory as the assembly
    char r2r_path[PATH_MAX];
    const char *last_slash = strrchr(context->assembly_path, '/');
    size_t dir_len = last_slash ? (size_t)(last_slash - context->assembly_path) : 0;
    if (dir_len >= sizeof(r2r_path) - 1)
        return false;

    strncpy(r2r_path, context->assembly_path, dir_len);
    int written = snprintf(r2r_path + dir_len, sizeof(r2r_path) - dir_len, "/%s", context->owner_composite_name);
    if (written <= 0 || (size_t)written >= sizeof(r2r_path) - dir_len)
        return false;

    void* handle = dlopen(r2r_path, RTLD_LAZY | RTLD_LOCAL);
    if (handle == NULL)
        return false;