user37359: 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);
}


user5757: 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. 

37359: <p>Looking at the main API file <code>secp256k1.h</code> of the C library, we have:</p>

<pre><code>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);
</code></pre>

<p>Hence I am expecting the function <code>secp256k1_ec_pubkey_parse</code> to fail if any of the three pointer arguments are NULL. This is indeed the case when <code>pubkey</code> or <code>input</code> are <code>NULL</code> (and in fact if we set up a callback function with <code>secp256k1_context_set_illegal_callback</code>, it will be duly called with the appropriate return value). However <strong>this function succeeds on <code>NULL</code> context</strong>. 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:</p>

<pre><code>#include "secp256k1.h"
#include &lt;assert.h&gt;

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, &amp;pub, pub1, 33); 
  assert(return_value == 1);  // public key is indeed valid

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

  // secp2561k1_context_destroy
 secp256k1_context_destroy(ctx);
}
</code></pre>
 5757: <p>If you look at <a href="https://github.com/bitcoin-core/secp256k1/blob/master/src/secp256k1.c" rel="nofollow noreferrer">the source code</a>, <code>secp256k1_ec_pubkey_parse</code> doesn't actually use its <code>ctx</code> argument.  So no harm is done if it's null.</p>

<p>You can see in the code that there is a <code>VERIFY_CHECK</code> macro to test if <code>ctx</code> is non-null.  However, this is meant only for testing; you can see in <a href="https://github.com/bitcoin-core/secp256k1/blob/master/src/util.h" rel="nofollow noreferrer">util.h</a> that nothing is actually done about the test unless the <code>VERIFY</code> macro is defined, which presumably is only the case for test builds.</p>

<p>The <code>SECP256K1_ARG_NONNULL</code> macro, defined <a href="https://github.com/bitcoin-core/secp256k1/blob/6e066962b7e4e9116194d7acd518da2ed2b7713f/include/secp256k1.h" rel="nofollow noreferrer">here</a>, uses the GCC <a href="https://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Function-Attributes.html" rel="nofollow noreferrer">function attribute mechanism</a> 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 <code>-Wnonnull</code> option. </p>
