<commit_before>/*
 * Copyright 2016 The Netty Project
 *
 * The Netty Project licenses this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */

#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "netty_unix_util.h"

static const uint64_t NETTY_BILLION = 1000000000L;

#ifdef NETTY_USE_MACH_INSTEAD_OF_CLOCK

#include <mach/mach.h>
#include <mach/mach_time.h>

#endif /* NETTY_USE_MACH_INSTEAD_OF_CLOCK */

char* netty_unix_util_prepend(const char* prefix, const char* str) {
    char* result = NULL;
    if (prefix == NULL) {
        if ((result = (char*) malloc(sizeof(char) * (strlen(str) + 1))) == NULL) {
            return NULL;
        }
        strcpy(result, str);
        return result;
    }
    if ((result = (char*) malloc(sizeof(char) * (strlen(prefix) + strlen(str) + 1))) == NULL) {
        return NULL;
    }
    strcpy(result, prefix);
    strcat(result, str);
    return result;
}

char* netty_unix_util_rstrstr(char* s1rbegin, const char* s1rend, const char* s2) {
    size_t s2len = strlen(s2);
    char *s = s1rbegin - s2len;

    for (; s >= s1rend; --s) {
        if (strncmp(s, s2, s2len) == 0) {
            return s;
        }
    }
    return NULL;
}

static char* netty_unix_util_strstr_last(const char* haystack, const char* needle) {
    char* prevptr = NULL;
    char* ptr = (char*) haystack;

    while ((ptr = strstr(ptr, needle)) != NULL) {
        // Just store the ptr and continue searching.
        prevptr = ptr;
        ++ptr;
    }
    return prevptr;
}

char* netty_unix_util_parse_package_prefix(const char* libraryPathName, const char* libraryName, jint* status) {
    char* packageNameEnd = netty_unix_util_strstr_last(libraryPathName, libraryName);<commit_msg>Add NULL checks to fix possible undefined behavior (#10718)<commit_after>/*
 * Copyright 2016 The Netty Project
 *
 * The Netty Project licenses this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */

#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "netty_unix_util.h"

static const uint64_t NETTY_BILLION = 1000000000L;

#ifdef NETTY_USE_MACH_INSTEAD_OF_CLOCK

#include <mach/mach.h>
#include <mach/mach_time.h>

#endif /* NETTY_USE_MACH_INSTEAD_OF_CLOCK */

char* netty_unix_util_prepend(const char* prefix, const char* str) {
    if (str == NULL) {
        // If str is NULL we should just return NULL as passing NULL to strlen is undefined behavior.
        return NULL;
    }
    char* result = NULL;
    if (prefix == NULL) {
        if ((result = (char*) malloc(sizeof(char) * (strlen(str) + 1))) == NULL) {
            return NULL;
        }
        strcpy(result, str);
        return result;
    }
    if ((result = (char*) malloc(sizeof(char) * (strlen(prefix) + strlen(str) + 1))) == NULL) {
        return NULL;
    }
    strcpy(result, prefix);
    strcat(result, str);
    return result;
}

char* netty_unix_util_rstrstr(char* s1rbegin, const char* s1rend, const char* s2) {
    if (s1rbegin == NULL || s1rend == NULL || s2 == NULL) {
        // Return NULL if any of the parameters is NULL to not risk a segfault
        return NULL;
    }
    size_t s2len = strlen(s2);
    char *s = s1rbegin - s2len;

    for (; s >= s1rend; --s) {
        if (strncmp(s, s2, s2len) == 0) {
            return s;
        }
    }
    return NULL;
}

static char* netty_unix_util_strstr_last(const char* haystack, const char* needle) {
    if (haystack == NULL || needle == NULL) {
        // calling strstr with NULL is undefined behavior. Better just return NULL and not risk a crash.
        return NULL;
    }

    char* prevptr = NULL;
    char* ptr = (char*) haystack;

    while ((ptr = strstr(ptr, needle)) != NULL) {
        // Just store the ptr and continue searching.
        prevptr = ptr;
        ++ptr;
    }
    return prevptr;
}

char* netty_unix_util_parse_package_prefix(const char* libraryPathName, const char* libraryName, jint* status) {
    char* packageNameEnd = netty_unix_util_strstr_last(libraryPathName, libraryName);
{'fraction_non_alphanumeric': 0.10973415950429742, 'fraction_numerical': 0.014791125324805117, 'mean_word_length': 3.0848979591836736, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, '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': '4737569', 'n_tokens_mistral': 1666, 'n_tokens_neox': 1609, 'n_words': 531}