<commit_before>/*****************************************************************************
 * Licensed to Qualys, Inc. (QUALYS) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * QUALYS 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.
 ****************************************************************************/

/**
 * @file
 * @brief IronBee --- IP Set Implementation
 *
 * See ib_ipset4_t for details.
 *
 * @author <NAME> <<EMAIL>>
 * @nosubgrouping
 */

#include "ironbee_config_auto.h"

#include <ironbee/ipset.h>
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>

/**
 * Helper typedef of a stdlib compare function.
 */
typedef int (*ib_ipset_compare_fn)(const void *, const void *);

/**
 * The mask \f$1^{bits}0^{32-bits}\f$.
 *
 * @param[in] bits Number of 1s.
 * @return Bit mask, \f$1^{bits}0^{32-bits}\f$, as a uint32_t.
 */
static
uint32_t ib_ipset4_mask(size_t bits)
{
    /* Special case. */
    if (bits >= 32) {
        return 0xffffffff;
    }
    return ~(0xffffffff >> bits);
}

/**
 * Return canonical address of @a net. (v4 version)
 *
 * @param[in] net Network to check for canonicalness.
 * @return Address of @a net with all bits outside of mask set to 0.
 */
static
ib_ip4_t ib_ipset4_canonical(
    ib_ip4_network_t net
)
{
    return net.ip & ib_ipset4_mask(net.size);
}

/**
 * Return canonical address of @a net. (v6 version)
 *
 * @param[in] net Network to check for canonicalness.
 * @return Address of @a net with all bits outside of mask set to 0.
 */
static
ib_ip6_t ib_ipset6_canonical(
    ib_ip6_network_t net
)
{
    ib_ip6_t ip = {{0, 0, 0, 0}};

    size_t initial_bytes = net.size / 32;
    size_t initial_bits  = net.size % 32;

    for (size_t i = 0; i < initial_bytes; ++i) {
        ip.ip[i] = net.ip.ip[i];
    }
    if (initial_bytes < 4) {
        ip.ip[initial_bytes] =
            net.ip.ip[initial_bytes] & ib_ipset4_mask(initial_bits);
    }
    return ip;
}

/**
 * True iff @a a_net is a prefix of @a b_net (v4 version).
 *
 * @param[in] a_net Network to check if prefix.
 * @param[in] b_net Network to check if prefix of.
 * @return true iff @a a_net is a prefix of @a b_net.
 */
static
bool ib_ipset4_is_prefix(
    ib_ip4_network_t a_net,
    ib_ip4_network_t b_net
)
{
    return
        (b_net.ip & ib_ipset4_mask(a_net.size)) ==
        (a_net.ip & ib_ipset4_mask(a_net.size))
        ;
}
<commit_msg>util/ipset: Fix edge case in ib_ipset4_is_prefix(). (CID 1062957)<commit_after>/*****************************************************************************
 * Licensed to Qualys, Inc. (QUALYS) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * QUALYS 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.
 ****************************************************************************/

/**
 * @file
 * @brief IronBee --- IP Set Implementation
 *
 * See ib_ipset4_t for details.
 *
 * @author <NAME> <<EMAIL>>
 * @nosubgrouping
 */

#include "ironbee_config_auto.h"

#include <ironbee/ipset.h>
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>

/**
 * Helper typedef of a stdlib compare function.
 */
typedef int (*ib_ipset_compare_fn)(const void *, const void *);

/**
 * The mask \f$1^{bits}0^{32-bits}\f$.
 *
 * @param[in] bits Number of 1s.
 * @return Bit mask, \f$1^{bits}0^{32-bits}\f$, as a uint32_t.
 */
static
uint32_t ib_ipset4_mask(size_t bits)
{
    /* Special case. */
    if (bits >= 32) {
        return 0xffffffff;
    }
    return ~(0xffffffff >> bits);
}

/**
 * Return canonical address of @a net. (v4 version)
 *
 * @param[in] net Network to check for canonicalness.
 * @return Address of @a net with all bits outside of mask set to 0.
 */
static
ib_ip4_t ib_ipset4_canonical(
    ib_ip4_network_t net
)
{
    return net.ip & ib_ipset4_mask(net.size);
}

/**
 * Return canonical address of @a net. (v6 version)
 *
 * @param[in] net Network to check for canonicalness.
 * @return Address of @a net with all bits outside of mask set to 0.
 */
static
ib_ip6_t ib_ipset6_canonical(
    ib_ip6_network_t net
)
{
    ib_ip6_t ip = {{0, 0, 0, 0}};

    size_t initial_bytes = net.size / 32;
    size_t initial_bits  = net.size % 32;

    for (size_t i = 0; i < initial_bytes; ++i) {
        ip.ip[i] = net.ip.ip[i];
    }
    if (initial_bytes < 4) {
        ip.ip[initial_bytes] =
            net.ip.ip[initial_bytes] & ib_ipset4_mask(initial_bits);
    }
    return ip;
}

/**
 * True iff @a a_net is a prefix of @a b_net (v4 version).
 *
 * @param[in] a_net Network to check if prefix.
 * @param[in] b_net Network to check if prefix of.
 * @return true iff @a a_net is a prefix of @a b_net.
 */
static
bool ib_ipset4_is_prefix(
    ib_ip4_network_t a_net,
    ib_ip4_network_t b_net
)
{
    /* Note that use of a_net.size on both sides is correct. */
    return
        a_net.size <= b_net.size &&
        (
            (b_net.ip & ib_ipset4_mask(a_net.size)) ==
            (a_net.ip & ib_ipset4_mask(a_net.size))
        )
        ;
}

{'fraction_non_alphanumeric': 0.15931056701030927, 'fraction_numerical': 0.01804123711340206, 'mean_word_length': 3.2702888583218708, 'pattern_counts': {'":': 0, '<': 22, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 4, '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': '4958007', 'n_tokens_mistral': 2150, 'n_tokens_neox': 2051, 'n_words': 675}