1

Looking at the main API file secp256k1.h of the C library, we have:

SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_parse(
    const secp256k1_context* ctx,
    secp256k1_pubkey* pubkey,
    const unsigned char *input,
    size_t inputlen
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);

Hence I am expecting the function secp256k1_ec_pubkey_parse to fail if any of the three pointer arguments are NULL. This is indeed the case when pubkey or input are NULL (and in fact if we set up a callback function with secp256k1_context_set_illegal_callback, it will be duly called with the appropriate return value). However this function succeeds on NULL context. Does anyone know why this is happening? Is this the expected behaviour? I am guessing this isn't very important, but I am trying to learn and I don't like it when I don't understand. I attach a C snippet:

#include "secp256k1.h"
#include <assert.h>

int main()
{
  int return_value;

  secp256k1_context *ctx;         
  secp256k1_pubkey pub;           

  ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);

  // This is a valid public key
  const unsigned char *pub1 = "\x03"
    "\xf0\x28\x89\x2b\xad\x7e\xd5\x7d\x2f\xb5\x7b\xf3\x30\x81\xd5\xcf"
    "\xcf\x6f\x9e\xd3\xd3\xd7\xf1\x59\xc2\xe2\xff\xf5\x79\xdc\x34\x1a";

  // secp256k1_ec_pubkey_parse
  return_value = secp256k1_ec_pubkey_parse(ctx, &pub, pub1, 33); 
  assert(return_value == 1);  // public key is indeed valid

  // same call with NULL context
  return_value = secp256k1_ec_pubkey_parse(NULL, &pub, pub1, 33); 
  assert(return_value == 1);  // call is successfull

  // secp2561k1_context_destroy
 secp256k1_context_destroy(ctx);
}
3

If you look at the source code, secp256k1_ec_pubkey_parse doesn't actually use its ctx argument. So no harm is done if it's null.

You can see in the code that there is a VERIFY_CHECK macro to test if ctx is non-null. However, this is meant only for testing; you can see in util.h that nothing is actually done about the test unless the VERIFY macro is defined, which presumably is only the case for test builds.

The SECP256K1_ARG_NONNULL macro, defined here, uses the GCC function attribute mechanism to tell the compiler that this argument is supposed to be non-null. The compiler will optimize on this basis. It can try to issue a warning if it can determine, at compile time, that the argument is null; but only if you use the -Wnonnull option.

  • 1
    I think the macro SECP256K1_BUILD is probably defined during the build process, and this has the effect of reducing SECP256K1_ARG_NONNULL(_x) to the empty string, thereby removing the __nonnull__ gcc attribute. – Sven Williamson Mar 5 '17 at 16:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.