Plug memory leaks in kx_ functions
If we, for some reason, fail to the error-path, then binaries allocated are not being released properly back to the erlang runtime. Fix this in the usual fashion by using a stack of undo-operations, and thread them via goto.
This commit is contained in:
+67
-26
@@ -48,63 +48,104 @@ ERL_NIF_TERM enacl_crypto_kx_keypair(ErlNifEnv *env, int argc,
|
||||
ERL_NIF_TERM
|
||||
enacl_crypto_kx_server_session_keys(ErlNifEnv *env, int argc,
|
||||
ERL_NIF_TERM const argv[]) {
|
||||
ERL_NIF_TERM ret;
|
||||
ErlNifBinary rx, tx, server_pk, server_sk, client_pk;
|
||||
|
||||
if ((argc != 3) || (!enif_inspect_binary(env, argv[0], &server_pk)) ||
|
||||
(!enif_inspect_binary(env, argv[1], &server_sk)) ||
|
||||
(!enif_inspect_binary(env, argv[2], &client_pk)) ||
|
||||
(server_pk.size != crypto_kx_PUBLICKEYBYTES) ||
|
||||
(server_sk.size != crypto_kx_SECRETKEYBYTES) ||
|
||||
(client_pk.size != crypto_kx_PUBLICKEYBYTES)) {
|
||||
return enif_make_badarg(env);
|
||||
}
|
||||
if (argc != 3)
|
||||
goto bad_arg;
|
||||
if (!enif_inspect_binary(env, argv[0], &server_pk))
|
||||
goto bad_arg;
|
||||
if (!enif_inspect_binary(env, argv[1], &server_sk))
|
||||
goto bad_arg;
|
||||
if (!enif_inspect_binary(env, argv[2], &client_pk))
|
||||
goto bad_arg;
|
||||
|
||||
if (server_pk.size != crypto_kx_PUBLICKEYBYTES)
|
||||
goto bad_arg;
|
||||
if (server_sk.size != crypto_kx_SECRETKEYBYTES)
|
||||
goto bad_arg;
|
||||
if (client_pk.size != crypto_kx_PUBLICKEYBYTES)
|
||||
goto bad_arg;
|
||||
|
||||
if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &rx)) {
|
||||
return nacl_error_tuple(env, "alloc_failed");
|
||||
ret = nacl_error_tuple(env, "alloc_failed");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &tx)) {
|
||||
return nacl_error_tuple(env, "alloc_failed");
|
||||
ret = nacl_error_tuple(env, "alloc_failed");
|
||||
goto release_rx;
|
||||
}
|
||||
|
||||
if (0 != crypto_kx_server_session_keys(rx.data, tx.data, server_pk.data,
|
||||
server_sk.data, client_pk.data)) {
|
||||
// suspicious client public key
|
||||
return nacl_error_tuple(env, "invalid_client_public_key");
|
||||
ret = nacl_error_tuple(env, "invalid_client_public_key");
|
||||
goto release_tx;
|
||||
}
|
||||
|
||||
return enif_make_tuple2(env, enif_make_binary(env, &rx),
|
||||
enif_make_binary(env, &tx));
|
||||
ret = enif_make_tuple2(env, enif_make_binary(env, &rx),
|
||||
enif_make_binary(env, &tx));
|
||||
goto done;
|
||||
|
||||
bad_arg:
|
||||
return enif_make_badarg(env);
|
||||
release_tx:
|
||||
enif_release_binary(&tx);
|
||||
release_rx:
|
||||
enif_release_binary(&rx);
|
||||
done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
ERL_NIF_TERM
|
||||
enacl_crypto_kx_client_session_keys(ErlNifEnv *env, int argc,
|
||||
ERL_NIF_TERM const argv[]) {
|
||||
ErlNifBinary rx, tx, client_pk, client_sk, server_pk;
|
||||
ERL_NIF_TERM ret;
|
||||
|
||||
if ((argc != 3) || (!enif_inspect_binary(env, argv[0], &client_pk)) ||
|
||||
(!enif_inspect_binary(env, argv[1], &client_sk)) ||
|
||||
(!enif_inspect_binary(env, argv[2], &server_pk)) ||
|
||||
(client_pk.size != crypto_kx_PUBLICKEYBYTES) ||
|
||||
(client_sk.size != crypto_kx_SECRETKEYBYTES) ||
|
||||
(server_pk.size != crypto_kx_PUBLICKEYBYTES)) {
|
||||
return enif_make_badarg(env);
|
||||
}
|
||||
if (argc != 3)
|
||||
goto bad_arg;
|
||||
if (!enif_inspect_binary(env, argv[0], &client_pk))
|
||||
goto bad_arg;
|
||||
if (!enif_inspect_binary(env, argv[1], &client_sk))
|
||||
goto bad_arg;
|
||||
if (!enif_inspect_binary(env, argv[2], &server_pk))
|
||||
goto bad_arg;
|
||||
|
||||
if (client_pk.size != crypto_kx_PUBLICKEYBYTES)
|
||||
goto bad_arg;
|
||||
if (client_sk.size != crypto_kx_SECRETKEYBYTES)
|
||||
goto bad_arg;
|
||||
if (server_pk.size != crypto_kx_PUBLICKEYBYTES)
|
||||
goto bad_arg;
|
||||
|
||||
if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &rx)) {
|
||||
return nacl_error_tuple(env, "alloc_failed");
|
||||
ret = nacl_error_tuple(env, "alloc_failed");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &tx)) {
|
||||
return nacl_error_tuple(env, "alloc_failed");
|
||||
ret = nacl_error_tuple(env, "alloc_failed");
|
||||
goto release_rx;
|
||||
}
|
||||
|
||||
if (0 != crypto_kx_client_session_keys(rx.data, tx.data, client_pk.data,
|
||||
client_sk.data, server_pk.data)) {
|
||||
// suspicious server public key
|
||||
return nacl_error_tuple(env, "invalid_server_public_key");
|
||||
ret = nacl_error_tuple(env, "invalid_server_public_key");
|
||||
goto release_tx;
|
||||
}
|
||||
|
||||
return enif_make_tuple2(env, enif_make_binary(env, &rx),
|
||||
enif_make_binary(env, &tx));
|
||||
ret = enif_make_tuple2(env, enif_make_binary(env, &rx),
|
||||
enif_make_binary(env, &tx));
|
||||
goto done;
|
||||
bad_arg:
|
||||
return enif_make_badarg(env);
|
||||
release_tx:
|
||||
enif_release_binary(&tx);
|
||||
release_rx:
|
||||
enif_release_binary(&rx);
|
||||
done:
|
||||
return ret;
|
||||
}
|
||||
Reference in New Issue
Block a user