<commit_before>#include "erl_nif.h"

#include <sodium.h>

#include "enacl.h"
#include "generichash.h"

typedef struct enacl_generichash_ctx {
  // The hash state
  crypto_generichash_state *ctx;
  // Is the context alive?
  int alive;
} enacl_generichash_ctx;

static ErlNifResourceType *enacl_generic_hash_ctx_rtype;

static void enacl_generic_hash_ctx_dtor(ErlNifEnv *env,
                                        enacl_generichash_ctx *);

int enacl_init_generic_hash_ctx(ErlNifEnv *env) {
  enacl_generic_hash_ctx_rtype =
      enif_open_resource_type(env, NULL, "enacl_generichash_context",
                              (ErlNifResourceDtor *)enacl_generic_hash_ctx_dtor,
                              ERL_NIF_RT_CREATE | ERL_NIF_RT_TAKEOVER, NULL);

  if (enacl_generic_hash_ctx_rtype == NULL)
    goto err;

  return 1;

err:
  return 0;
}

static void enacl_generic_hash_ctx_dtor(ErlNifEnv *env,
                                        enacl_generichash_ctx *obj) {
  if (!obj->alive) {
    return;
  }

  sodium_free(obj->ctx);
  return;
}

/*
 * Generic hash
 */
ERL_NIF_TERM enif_crypto_generichash_BYTES(ErlNifEnv *env, int argc,
                                           ERL_NIF_TERM const argv[]) {
  return enif_make_int64(env, crypto_generichash_BYTES);
}

ERL_NIF_TERM enif_crypto_generichash_BYTES_MIN(ErlNifEnv *env, int argc,
                                               ERL_NIF_TERM const argv[]) {
  return enif_make_int64(env, crypto_generichash_BYTES_MIN);
}

ERL_NIF_TERM enif_crypto_generichash_BYTES_MAX(ErlNifEnv *env, int argc,
                                               ERL_NIF_TERM const argv[]) {
  return enif_make_int64(env, crypto_generichash_BYTES_MAX);
}

ERL_NIF_TERM enif_crypto_generichash_KEYBYTES(ErlNifEnv *env, int argc,
                                              ERL_NIF_TERM const argv[]) {
  return enif_make_int64(env, crypto_generichash_KEYBYTES);
}

ERL_NIF_TERM enif_crypto_generichash_KEYBYTES_MIN(ErlNifEnv *env, int argc,
                                                  ERL_NIF_TERM const argv[]) {
  return enif_make_int64(env, crypto_generichash_KEYBYTES_MIN);
}

ERL_NIF_TERM enif_crypto_generichash_KEYBYTES_MAX(ErlNifEnv *env, int argc,
                                                  ERL_NIF_TERM const argv[]) {
  return enif_make_int64(env, crypto_generichash_KEYBYTES_MAX);
}

ERL_NIF_TERM enacl_crypto_generichash(ErlNifEnv *env, int argc,
                                      ERL_NIF_TERM const argv[]) {
  ErlNifBinary hash, message, key;
  unsigned hashSize;
  ERL_NIF_TERM ret;

  // Validate the arguments
  if ((argc != 3) || (!enif_get_uint(env, argv[0], &hashSize)) ||
      (!enif_inspect_binary(env, argv[1], &message)) ||
      (!enif_inspect_binary(env, argv[2], &key)))
    goto bad_arg;

  // Verify that hash size is
  // crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX
  if ((hashSize < crypto_generichash_BYTES_MIN) ||
      (hashSize > crypto_generichash_BYTES_MAX)) {
    ret = nacl_error_tuple(env, "invalid_hash_size");
    goto done;
  }

  // validate key size
  unsigned char *k = key.data;
  if (0 == key.size) {
    k = NULL;
  } else if (key.size < crypto_generichash_KEYBYTES_MIN ||
             key.size > crypto_generichash_KEYBYTES_MAX) {
    ret = nacl_error_tuple(env, "invalid_key_size");
    goto done;
  }

  // allocate memory for hash
  if (!enif_alloc_binary(hashSize, &hash)) {
    ret = nacl_error_tuple(env, "alloc_failed");
    goto done;
  }

  // calculate hash
  if (0 != crypto_generichash(hash.data, hash.size, message.data, message.size,
                              k, key.size)) {
    ret = nacl_error_tuple(env, "hash_error");
    goto release;
  }

  ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK);
  ERL_NIF_TERM ret_hash = enif_make_binary(env, &hash);

  ret = enif_make_tuple2(env, ok, ret_hash);
  goto done;

bad_arg:
  return enif_make_badarg(env);
release:
  enif_release_binary(&hash);
done:
  return ret;
}

ERL_NIF_TERM enacl_crypto_generichash_init(ErlNifEnv *env, int argc,
                                           ERL_NIF_TERM const argv[]) {
  ErlNifBinary key;
  unsigned hash_size;
  enacl_generichash_ctx *obj = NULL;
  ERL_NIF_TERM ret;

  // Validate the arguments
  if ((argc != 2) || (!enif_get_uint(env, argv[0], &hash_size)) ||
      (!enif_inspect_binary(env, argv[1], &key))) {
    goto bad_arg;
  }

  // Verify that hash size is
  // crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX
  if ((hash_size <= crypto_generichash_BYTES_MIN) ||
      (hash_size >= crypto_generichash_BYTES_MAX)) {
    ret = nacl_error_tuple(env, "invalid_hash_size");
    goto done;
  }

  // validate key size
  unsigned char *k = key.data;
  if (0 == key.size) {
    k = NULL;
  } else if (key.size <= crypto_generichash_KEYBYTES_MIN ||
             key.size >= crypto_generichash_KEYBYTES_MAX) {
    ret = nacl_error_tuple(env, "invalid_key_size");
    goto done;
  }

  // Create the resource
  if ((obj = enif_alloc_resource(enacl_generic_hash_ctx_rtype,
                                 sizeof(enacl_generichash_ctx))) == NULL) {
    goto err;
  }

  // Allocate the state context via libsodium
  // Note that this ensures a 64byte alignment for the resource
  // And also protects the resource via guardpages
  obj->ctx = NULL;
  obj->alive = 0;
  obj->ctx = (crypto_generichash_state *)sodium_malloc(
      crypto_generichash_statebytes());
  if (obj->ctx == NULL) {
    goto err;
  }
  obj->alive = 1;

  // Call the library function
  if (0 != crypto_generichash_init(obj->ctx, k, key.size, hash_size)) {
    ret = nacl_error_tuple(env, "hash_init_error");
    goto done;
  }

  // Create return values
  ERL_NIF_TERM e1 = enif_make_atom(env, "hashstate");
  ERL_NIF_TERM e2 = argv[0];
  ERL_NIF_TERM e3 = enif_make_resource(env, obj);

  ret = enif_make_tuple3(env, e1, e2, e3);
  goto done;
bad_arg:
  return enif_make_badarg(env);

err:
  ret = nacl_error_tuple(env, "internal_error");
  if (obj != NULL) {
    if (obj->alive) {
      sodium_free(obj->ctx);
    }
  }
done:
  if (obj != NULL) {
    enif_release_resource(obj);
  }
  return ret;
}

ERL_NIF_TERM enacl_crypto_generichash_update(ErlNifEnv *env, int argc,
                                             ERL_NIF_TERM const argv[]) {
  ERL_NIF_TERM ret;
  ErlNifBinary data;
  unsigned int data_size;
  enacl_generichash_ctx *obj = NULL;

  // Validate the arguments
  if (argc != 3)
    goto bad_arg;
  if (!enif_get_uint(env, argv[0], &data_size))
    goto bad_arg;
  if (!enif_get_resource(env, argv[1],
                         (ErlNifResourceType *)enacl_generic_hash_ctx_rtype,
                         (void **)&obj))
    goto bad_arg;
  if (!enif_inspect_binary(env, argv[2], &data))
    goto bad_arg;

  // Update hash state
  if (0 != crypto_generichash_update(obj->ctx, data.data, data.size)) {
    ret = nacl_error_tuple(env, "hash_update_error");
    goto done;
  }

  ERL_NIF_TERM e1 = enif_make_atom(env, "hashstate");
  ERL_NIF_TERM e2 = argv[0];
  ERL_NIF_TERM e3 = argv[1];

  ret = enif_make_tuple3(env, e1, e2, e3);
  goto done;

bad_arg:
  return enif_make_badarg(env);
done:
  return ret;
}

ERL_NIF_TERM enacl_crypto_generichash_final(ErlNifEnv *env, int argc,
                                            ERL_NIF_TERM const argv[]) {
  ERL_NIF_TERM ret;
  ErlNifBinary hash;
  unsigned int hash_size;
  enacl_generichash_ctx *obj = NULL;

  if (argc != 2)
    goto bad_arg;
  if (!enif_get_uint(env, argv[0], &hash_size))
    goto bad_arg;
  if (!enif_get_resource(env, argv[1], enacl_generic_hash_ctx_rtype,
                         (void **)&obj))
    goto bad_arg;

  if ((hash_size <= crypto_generichash_BYTES_MIN) ||
      (hash_size >= crypto_generichash_BYTES_MAX)) {
    ret = nacl_error_tuple(env, "invalid_hash_size");
    goto done;
  }

  if (!enif_alloc_binary(hash_size, &hash)) {
    ret = nacl_error_tuple(env, "alloc_failed");
    goto done;
  }

  if (0 != crypto_generichash_final(obj->ctx, hash.data, hash.size)) {
    ret = nacl_error_tuple(env, "hash_error");
    goto release;
  }

  ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK);
  ERL_NIF_TERM h = enif_make_binary(env, &hash);

  ret = enif_make_tuple2(env, ok, h);
  goto done;

bad_arg:
  return enif_make_badarg(env);
release:
  enif_release_binary(&hash);
done:
  return ret;
}
<commit_msg>The sodium MIN/MAX values are incusive<commit_after>#include "erl_nif.h"

#include <sodium.h>

#include "enacl.h"
#include "generichash.h"

typedef struct enacl_generichash_ctx {
  // The hash state
  crypto_generichash_state *ctx;
  // Is the context alive?
  int alive;
} enacl_generichash_ctx;

static ErlNifResourceType *enacl_generic_hash_ctx_rtype;

static void enacl_generic_hash_ctx_dtor(ErlNifEnv *env,
                                        enacl_generichash_ctx *);

int enacl_init_generic_hash_ctx(ErlNifEnv *env) {
  enacl_generic_hash_ctx_rtype =
      enif_open_resource_type(env, NULL, "enacl_generichash_context",
                              (ErlNifResourceDtor *)enacl_generic_hash_ctx_dtor,
                              ERL_NIF_RT_CREATE | ERL_NIF_RT_TAKEOVER, NULL);

  if (enacl_generic_hash_ctx_rtype == NULL)
    goto err;

  return 1;

err:
  return 0;
}

static void enacl_generic_hash_ctx_dtor(ErlNifEnv *env,
                                        enacl_generichash_ctx *obj) {
  if (!obj->alive) {
    return;
  }

  sodium_free(obj->ctx);
  return;
}

/*
 * Generic hash
 */
ERL_NIF_TERM enif_crypto_generichash_BYTES(ErlNifEnv *env, int argc,
                                           ERL_NIF_TERM const argv[]) {
  return enif_make_int64(env, crypto_generichash_BYTES);
}

ERL_NIF_TERM enif_crypto_generichash_BYTES_MIN(ErlNifEnv *env, int argc,
                                               ERL_NIF_TERM const argv[]) {
  return enif_make_int64(env, crypto_generichash_BYTES_MIN);
}

ERL_NIF_TERM enif_crypto_generichash_BYTES_MAX(ErlNifEnv *env, int argc,
                                               ERL_NIF_TERM const argv[]) {
  return enif_make_int64(env, crypto_generichash_BYTES_MAX);
}

ERL_NIF_TERM enif_crypto_generichash_KEYBYTES(ErlNifEnv *env, int argc,
                                              ERL_NIF_TERM const argv[]) {
  return enif_make_int64(env, crypto_generichash_KEYBYTES);
}

ERL_NIF_TERM enif_crypto_generichash_KEYBYTES_MIN(ErlNifEnv *env, int argc,
                                                  ERL_NIF_TERM const argv[]) {
  return enif_make_int64(env, crypto_generichash_KEYBYTES_MIN);
}

ERL_NIF_TERM enif_crypto_generichash_KEYBYTES_MAX(ErlNifEnv *env, int argc,
                                                  ERL_NIF_TERM const argv[]) {
  return enif_make_int64(env, crypto_generichash_KEYBYTES_MAX);
}

ERL_NIF_TERM enacl_crypto_generichash(ErlNifEnv *env, int argc,
                                      ERL_NIF_TERM const argv[]) {
  ErlNifBinary hash, message, key;
  unsigned hashSize;
  ERL_NIF_TERM ret;

  // Validate the arguments
  if ((argc != 3) || (!enif_get_uint(env, argv[0], &hashSize)) ||
      (!enif_inspect_binary(env, argv[1], &message)) ||
      (!enif_inspect_binary(env, argv[2], &key)))
    goto bad_arg;

  // Verify that hash size is
  // crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX
  if ((hashSize <= crypto_generichash_BYTES_MIN) ||
      (hashSize >= crypto_generichash_BYTES_MAX)) {
    ret = nacl_error_tuple(env, "invalid_hash_size");
    goto done;
  }

  // validate key size
  unsigned char *k = key.data;
  if (0 == key.size) {
    k = NULL;
  } else if (key.size <= crypto_generichash_KEYBYTES_MIN ||
             key.size >= crypto_generichash_KEYBYTES_MAX) {
    ret = nacl_error_tuple(env, "invalid_key_size");
    goto done;
  }

  // allocate memory for hash
  if (!enif_alloc_binary(hashSize, &hash)) {
    ret = nacl_error_tuple(env, "alloc_failed");
    goto done;
  }

  // calculate hash
  if (0 != crypto_generichash(hash.data, hash.size, message.data, message.size,
                              k, key.size)) {
    ret = nacl_error_tuple(env, "hash_error");
    goto release;
  }

  ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK);
  ERL_NIF_TERM ret_hash = enif_make_binary(env, &hash);

  ret = enif_make_tuple2(env, ok, ret_hash);
  goto done;

bad_arg:
  return enif_make_badarg(env);
release:
  enif_release_binary(&hash);
done:
  return ret;
}

ERL_NIF_TERM enacl_crypto_generichash_init(ErlNifEnv *env, int argc,
                                           ERL_NIF_TERM const argv[]) {
  ErlNifBinary key;
  unsigned hash_size;
  enacl_generichash_ctx *obj = NULL;
  ERL_NIF_TERM ret;

  // Validate the arguments
  if ((argc != 2) || (!enif_get_uint(env, argv[0], &hash_size)) ||
      (!enif_inspect_binary(env, argv[1], &key))) {
    goto bad_arg;
  }

  // Verify that hash size is
  // crypto_generichash_BYTES/crypto_generichash_BYTES_MIN/crypto_generichash_BYTES_MAX
  if ((hash_size <= crypto_generichash_BYTES_MIN) ||
      (hash_size >= crypto_generichash_BYTES_MAX)) {
    ret = nacl_error_tuple(env, "invalid_hash_size");
    goto done;
  }

  // validate key size
  unsigned char *k = key.data;
  if (0 == key.size) {
    k = NULL;
  } else if (key.size <= crypto_generichash_KEYBYTES_MIN ||
             key.size >= crypto_generichash_KEYBYTES_MAX) {
    ret = nacl_error_tuple(env, "invalid_key_size");
    goto done;
  }

  // Create the resource
  if ((obj = enif_alloc_resource(enacl_generic_hash_ctx_rtype,
                                 sizeof(enacl_generichash_ctx))) == NULL) {
    goto err;
  }

  // Allocate the state context via libsodium
  // Note that this ensures a 64byte alignment for the resource
  // And also protects the resource via guardpages
  obj->ctx = NULL;
  obj->alive = 0;
  obj->ctx = (crypto_generichash_state *)sodium_malloc(
      crypto_generichash_statebytes());
  if (obj->ctx == NULL) {
    goto err;
  }
  obj->alive = 1;

  // Call the library function
  if (0 != crypto_generichash_init(obj->ctx, k, key.size, hash_size)) {
    ret = nacl_error_tuple(env, "hash_init_error");
    goto done;
  }

  // Create return values
  ERL_NIF_TERM e1 = enif_make_atom(env, "hashstate");
  ERL_NIF_TERM e2 = argv[0];
  ERL_NIF_TERM e3 = enif_make_resource(env, obj);

  ret = enif_make_tuple3(env, e1, e2, e3);
  goto done;
bad_arg:
  return enif_make_badarg(env);

err:
  ret = nacl_error_tuple(env, "internal_error");
  if (obj != NULL) {
    if (obj->alive) {
      sodium_free(obj->ctx);
    }
  }
done:
  if (obj != NULL) {
    enif_release_resource(obj);
  }
  return ret;
}

ERL_NIF_TERM enacl_crypto_generichash_update(ErlNifEnv *env, int argc,
                                             ERL_NIF_TERM const argv[]) {
  ERL_NIF_TERM ret;
  ErlNifBinary data;
  unsigned int data_size;
  enacl_generichash_ctx *obj = NULL;

  // Validate the arguments
  if (argc != 3)
    goto bad_arg;
  if (!enif_get_uint(env, argv[0], &data_size))
    goto bad_arg;
  if (!enif_get_resource(env, argv[1],
                         (ErlNifResourceType *)enacl_generic_hash_ctx_rtype,
                         (void **)&obj))
    goto bad_arg;
  if (!enif_inspect_binary(env, argv[2], &data))
    goto bad_arg;

  // Update hash state
  if (0 != crypto_generichash_update(obj->ctx, data.data, data.size)) {
    ret = nacl_error_tuple(env, "hash_update_error");
    goto done;
  }

  ERL_NIF_TERM e1 = enif_make_atom(env, "hashstate");
  ERL_NIF_TERM e2 = argv[0];
  ERL_NIF_TERM e3 = argv[1];

  ret = enif_make_tuple3(env, e1, e2, e3);
  goto done;

bad_arg:
  return enif_make_badarg(env);
done:
  return ret;
}

ERL_NIF_TERM enacl_crypto_generichash_final(ErlNifEnv *env, int argc,
                                            ERL_NIF_TERM const argv[]) {
  ERL_NIF_TERM ret;
  ErlNifBinary hash;
  unsigned int hash_size;
  enacl_generichash_ctx *obj = NULL;

  if (argc != 2)
    goto bad_arg;
  if (!enif_get_uint(env, argv[0], &hash_size))
    goto bad_arg;
  if (!enif_get_resource(env, argv[1], enacl_generic_hash_ctx_rtype,
                         (void **)&obj))
    goto bad_arg;

  if ((hash_size <= crypto_generichash_BYTES_MIN) ||
      (hash_size >= crypto_generichash_BYTES_MAX)) {
    ret = nacl_error_tuple(env, "invalid_hash_size");
    goto done;
  }

  if (!enif_alloc_binary(hash_size, &hash)) {
    ret = nacl_error_tuple(env, "alloc_failed");
    goto done;
  }

  if (0 != crypto_generichash_final(obj->ctx, hash.data, hash.size)) {
    ret = nacl_error_tuple(env, "hash_error");
    goto release;
  }

  ERL_NIF_TERM ok = enif_make_atom(env, ATOM_OK);
  ERL_NIF_TERM h = enif_make_binary(env, &hash);

  ret = enif_make_tuple2(env, ok, h);
  goto done;

bad_arg:
  return enif_make_badarg(env);
release:
  enif_release_binary(&hash);
done:
  return ret;
}

{'fraction_non_alphanumeric': 0.10463244500089429, 'fraction_numerical': 0.0067966374530495435, 'mean_word_length': 2.9477524123323136, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 46, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5279411', 'n_tokens_mistral': 6336, 'n_tokens_neox': 6238, 'n_words': 1199}