#include "orconfig.h"
#include "lib/ctime/di_ops.h"
#include "lib/err/torerr.h"
#include "lib/malloc/malloc.h"
#include <string.h>
int
tor_memcmp(const void *a, const void *b, size_t len)
{
#ifdef HAVE_TIMINGSAFE_MEMCMP
return timingsafe_memcmp(a, b, len);
#else
const uint8_t *x = a;
const uint8_t *y = b;
size_t i = len;
int retval = 0;
while (i--) {
int v1 = x[i];
int v2 = y[i];
int equal_p = v1 ^ v2;
--equal_p;
equal_p >>= 8;
#if ((-60 >> 8) != -1)
#error "cpp says right-shift doesn't perform sign-extension."
#endif
#ifndef RSHIFT_DOES_SIGN_EXTEND
#error "configure says right-shift doesn't perform sign-extension."
#endif
retval &= equal_p;
retval += (v1 - v2);
}
return retval;
#endif
}
int
tor_memeq(const void *a, const void *b, size_t sz)
{
const uint8_t *ba = a, *bb = b;
uint32_t any_difference = 0;
while (sz--) {
const uint8_t byte_diff = *ba++ ^ *bb++;
any_difference |= byte_diff;
}
return 1 & ((any_difference - 1) >> 8);
}
struct di_digest256_map_t {
struct di_digest256_map_t *next;
uint8_t key[32];
void *val;
};
void
dimap_free_(di_digest256_map_t *map, dimap_free_fn free_fn)
{
while (map) {
di_digest256_map_t *victim = map;
map = map->next;
if (free_fn)
free_fn(victim->val);
tor_free(victim);
}
}
void
dimap_add_entry(di_digest256_map_t **map,
const uint8_t *key, void *val)
{
di_digest256_map_t *new_ent;
{
void *old_val = dimap_search(*map, key, NULL);
raw_assert(! old_val);
raw_assert(val);
}
new_ent = tor_malloc_zero(sizeof(di_digest256_map_t));
new_ent->next = *map;
memcpy(new_ent->key, key, 32);
new_ent->val = val;
*map = new_ent;
}
void *
dimap_search(const di_digest256_map_t *map, const uint8_t *key,
void *dflt_val)
{
uintptr_t result = (uintptr_t)dflt_val;
while (map) {
uintptr_t r = (uintptr_t) tor_memeq(map->key, key, 32);
r -= 1;
result &= r;
result |= ((uintptr_t)(map->val)) & ~r;
map = map->next;
}
return (void *)result;
}
int
safe_mem_is_zero(const void *mem, size_t sz)
{
uint32_t total = 0;
const uint8_t *ptr = mem;
while (sz--) {
total |= *ptr++;
}
return 1 & ((total - 1) >> 8);
}
#if SIZEOF_VOID_P == 8
#define gt_i64_timei(a,b) ((a) > (b))
#else
static inline int
gt_i64_timei(uint64_t a, uint64_t b)
{
int64_t diff = (int64_t) (b - a);
int res = diff >> 63;
return res & 1;
}
#endif
int
select_array_member_cumulative_timei(const uint64_t *entries, int n_entries,
uint64_t total, uint64_t rand_val)
{
int i, i_chosen=-1, n_chosen=0;
uint64_t total_so_far = 0;
for (i = 0; i < n_entries; ++i) {
total_so_far += entries[i];
if (gt_i64_timei(total_so_far, rand_val)) {
i_chosen = i;
n_chosen++;
rand_val = INT64_MAX;
}
}
raw_assert(total_so_far == total);
raw_assert(n_chosen == 1);
raw_assert(i_chosen >= 0);
raw_assert(i_chosen < n_entries);
return i_chosen;
}
void
memcpy_if_true_timei(bool s, void *dest, const void *src, size_t n)
{
const char mask = (char) -(signed char)s;
char *destp = dest;
const char *srcp = src;
for (size_t i = 0; i < n; ++i) {
*destp = (*destp & ~mask) | (*srcp & mask);
++destp;
++srcp;
}
}