commit 43e9029031dde0a7679b885db6f838878783c884
parent 073b76e9057087fbf0dae15921c558495281f1bf
Author: Christian Grothoff <grothoff@gnunet.org>
Date: Thu, 1 May 2025 15:10:26 +0200
fix error handling on internal invariant violation
Diffstat:
2 files changed, 56 insertions(+), 78 deletions(-)
diff --git a/src/exchange/taler-exchange-httpd_melt_v27.c b/src/exchange/taler-exchange-httpd_melt_v27.c
@@ -267,19 +267,22 @@ struct MeltContext
*/
#define SET_ERROR(mc, ec) \
do \
- { (mc)->error.code = (ec); \
+ { GNUNET_static_assert (MELT_ERROR_NONE != ec); \
+ (mc)->error.code = (ec); \
(mc)->phase = MELT_PHASE_GENERATE_REPLY_ERROR; } while (0)
#define SET_ERROR_WITH_FIELD(mc, ec, field) \
do \
- { (mc)->error.code = (ec); \
- (mc)->error.details.field = (field); \
+ { GNUNET_static_assert (MELT_ERROR_NONE != ec); \
+ (mc)->error.code = (ec); \
+ (mc)->error.details.field = (field); \
(mc)->phase = MELT_PHASE_GENERATE_REPLY_ERROR; } while (0)
#define SET_ERROR_WITH_DETAIL(mc, ec, field, value) \
do \
- { (mc)->error.code = (ec); \
- (mc)->error.details.field = (value); \
+ { GNUNET_static_assert (MELT_ERROR_NONE != ec); \
+ (mc)->error.code = (ec); \
+ (mc)->error.details.field = (value); \
(mc)->phase = MELT_PHASE_GENERATE_REPLY_ERROR; } while (0)
@@ -424,8 +427,7 @@ phase_parse_request (
/* validate array size */
GNUNET_static_assert (
- TALER_MAX_COINS < INT_MAX / TALER_CNC_KAPPA,
- "TALER_MAX_COINS too large");
+ TALER_MAX_COINS < INT_MAX / TALER_CNC_KAPPA);
mc->request.refresh.num_coins = json_array_size (j_denoms_h);
if (0 == mc->request.refresh.num_coins)
@@ -1109,8 +1111,7 @@ phase_prepare_transaction (
mc->request.refresh.cs_r_choices |= bit << i;
GNUNET_static_assert (
TALER_MAX_COINS <=
- sizeof(mc->request.refresh.cs_r_choices) * 8,
- "TALER_MAX_COINS too large");
+ sizeof(mc->request.refresh.cs_r_choices) * 8);
}
}
}
@@ -1220,8 +1221,8 @@ phase_generate_reply_error (
GNUNET_assert (MELT_PHASE_GENERATE_REPLY_ERROR == mc->phase);
GNUNET_assert (MELT_ERROR_NONE != mc->error.code);
- if (IDEMPOTENCY_CHECK_REQUIRED (mc->error.code)
- && melt_is_idempotent (mc))
+ if (IDEMPOTENCY_CHECK_REQUIRED (mc->error.code) &&
+ melt_is_idempotent (mc))
{
return;
}
@@ -1229,10 +1230,7 @@ phase_generate_reply_error (
switch (mc->error.code)
{
case MELT_ERROR_NONE:
- GNUNET_break (0);
- mc->phase = MELT_PHASE_RETURN_YES;
- return;
-
+ break;
case MELT_ERROR_REQUEST_PARAMETER_MALFORMED:
finish_loop (mc,
TALER_MHD_reply_with_error (
@@ -1240,8 +1238,7 @@ phase_generate_reply_error (
MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_PARAMETER_MALFORMED,
mc->error.details.request_parameter_malformed));
- break;
-
+ return;
case MELT_ERROR_KEYS_MISSING:
finish_loop (mc,
TALER_MHD_reply_with_error (
@@ -1249,8 +1246,7 @@ phase_generate_reply_error (
MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING,
NULL));
- break;
-
+ return;
case MELT_ERROR_DB_FETCH_FAILED:
finish_loop (mc,
TALER_MHD_reply_with_error (
@@ -1258,8 +1254,7 @@ phase_generate_reply_error (
MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_GENERIC_DB_FETCH_FAILED,
mc->error.details.db_fetch_context));
- break;
-
+ return;
case MELT_ERROR_DB_INVARIANT_FAILURE:
finish_loop (mc,
TALER_MHD_reply_with_error (
@@ -1267,8 +1262,7 @@ phase_generate_reply_error (
MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_GENERIC_DB_INVARIANT_FAILURE,
NULL));
- break;
-
+ return;
case MELT_ERROR_DB_PREFLIGHT_FAILURE:
finish_loop (mc,
TALER_MHD_reply_with_error (
@@ -1276,8 +1270,7 @@ phase_generate_reply_error (
MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_GENERIC_DB_COMMIT_FAILED,
"make_coin_known"));
- break;
-
+ return;
case MELT_ERROR_DB_MAKE_COIN_KNOW_FAILURE:
finish_loop (mc,
TALER_MHD_reply_with_error (
@@ -1285,57 +1278,50 @@ phase_generate_reply_error (
MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_GENERIC_DB_START_FAILED,
"preflight failure"));
- break;
-
+ return;
case MELT_ERROR_COIN_UNKNOWN:
finish_loop (mc,
TALER_MHD_reply_with_ec (
mc->rc->connection,
TALER_EC_EXCHANGE_GENERIC_COIN_UNKNOWN,
NULL));
- break;
-
+ return;
case MELT_COIN_CONFLICTING_DENOMINATION_KEY:
finish_loop (mc,
TALER_MHD_reply_with_ec (
mc->rc->connection,
TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_DENOMINATION_KEY,
TALER_B2S (&mc->error.details.denom_h)));
- break;
-
- case MELT_ERROR_COIN_EXPIRED_NO_ZOMBIE:
+ return;
+ case MELT_ERROR_COIN_EXPIRED_NO_ZOMBIE:
finish_loop (mc,
TALER_MHD_reply_with_error (
mc->rc->connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_EXCHANGE_MELT_COIN_EXPIRED_NO_ZOMBIE,
NULL));
- break;
-
+ return;
case MELT_ERROR_DENOMINATION_SIGN:
finish_loop (mc,
TALER_MHD_reply_with_ec (
mc->rc->connection,
mc->error.details.ec_denomination_sign,
NULL));
- break;
-
+ return;
case MELT_ERROR_DENOMINATION_SIGNATURE_INVALID:
finish_loop (mc,
TALER_MHD_reply_with_error (mc->rc->connection,
MHD_HTTP_FORBIDDEN,
TALER_EC_EXCHANGE_DENOMINATION_SIGNATURE_INVALID,
NULL));
- break;
-
+ return;
case MELT_ERROR_DENOMINATION_KEY_UNKNOWN:
GNUNET_break_op (0);
finish_loop (mc,
TEH_RESPONSE_reply_unknown_denom_pub_hash (
mc->rc->connection,
&mc->error.details.denom_h));
- break;
-
+ return;
case MELT_ERROR_DENOMINATION_EXPIRED:
GNUNET_break_op (0);
finish_loop (mc,
@@ -1344,8 +1330,7 @@ phase_generate_reply_error (
&mc->error.details.denom_h,
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_EXPIRED,
"MELT"));
- break;
-
+ return;
case MELT_ERROR_DENOMINATION_VALIDITY_IN_FUTURE:
finish_loop (mc,
TEH_RESPONSE_reply_expired_denom_pub_hash (
@@ -1353,8 +1338,7 @@ phase_generate_reply_error (
&mc->error.details.denom_h,
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_VALIDITY_IN_FUTURE,
"MELT"));
- break;
-
+ return;
case MELT_ERROR_DENOMINATION_REVOKED:
GNUNET_break_op (0);
finish_loop (mc,
@@ -1362,35 +1346,32 @@ phase_generate_reply_error (
mc->rc->connection,
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_REVOKED,
NULL));
- break;
-
+ return;
case MELT_ERROR_COIN_CIPHER_MISMATCH:
finish_loop (mc,
TALER_MHD_reply_with_ec (
mc->rc->connection,
TALER_EC_EXCHANGE_GENERIC_CIPHER_MISMATCH,
NULL));
- break;
-
+ return;
case MELT_ERROR_BLINDING_SEED_REQUIRED:
finish_loop (mc,
TALER_MHD_reply_with_ec (
mc->rc->connection,
TALER_EC_GENERIC_PARAMETER_MISSING,
"blinding_seed"));
- break;
-
+ return;
case MELT_ERROR_CRYPTO_HELPER:
finish_loop (mc,
TALER_MHD_reply_with_ec (
mc->rc->connection,
TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
NULL));
- break;
-
+ return;
case MELT_ERROR_AGE_RESTRICTION_NOT_SUPPORTED_BY_DENOMINATION:
{
char msg[256];
+
GNUNET_snprintf (msg,
sizeof(msg),
"denomination %s does not support age restriction",
@@ -1400,17 +1381,15 @@ phase_generate_reply_error (
mc->rc->connection,
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN,
msg));
- break;
+ return;
}
-
case MELT_ERROR_AGE_RESTRICTION_COMMITMENT_INVALID:
finish_loop (mc,
TALER_MHD_reply_with_ec (
mc->rc->connection,
TALER_EC_EXCHANGE_REFRESHES_REVEAL_AGE_RESTRICTION_COMMITMENT_INVALID,
"old_age_commitment_h"));
- break;
-
+ return;
case MELT_ERROR_AMOUNT_OVERFLOW:
finish_loop (mc,
TALER_MHD_reply_with_error (
@@ -1418,8 +1397,7 @@ phase_generate_reply_error (
MHD_HTTP_BAD_REQUEST,
TALER_EC_EXCHANGE_REFRESHES_REVEAL_COST_CALCULATION_OVERFLOW,
"amount"));
- break;
-
+ return;
case MELT_ERROR_AMOUNT_PLUS_FEE_OVERFLOW:
finish_loop (mc,
TALER_MHD_reply_with_error (
@@ -1427,16 +1405,14 @@ phase_generate_reply_error (
MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_EXCHANGE_REFRESHES_REVEAL_COST_CALCULATION_OVERFLOW,
"amount+fee"));
- break;
-
+ return;
case MELT_ERROR_FEES_EXCEED_CONTRIBUTION:
finish_loop (mc,
TALER_MHD_reply_with_error (mc->rc->connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_EXCHANGE_MELT_FEES_EXCEED_CONTRIBUTION,
NULL));
- break;
-
+ return;
case MELT_ERROR_AMOUNT_WITH_FEE_INCORRECT:
finish_loop (mc,
TALER_MHD_reply_with_error (
@@ -1444,16 +1420,14 @@ phase_generate_reply_error (
MHD_HTTP_BAD_REQUEST,
TALER_EC_EXCHANGE_REFRESHES_REVEAL_COST_CALCULATION_OVERFLOW,
"value_with_fee incorrect"));
- break;
-
+ return;
case MELT_ERROR_CONFIRMATION_SIGN:
finish_loop (mc,
TALER_MHD_reply_with_ec (
mc->rc->connection,
mc->error.details.ec_confirmation_sign,
NULL));
- break;
-
+ return;
case MELT_ERROR_INSUFFICIENT_FUNDS:
finish_loop (mc,
TEH_RESPONSE_reply_coin_insufficient_funds (
@@ -1461,8 +1435,7 @@ phase_generate_reply_error (
TALER_EC_EXCHANGE_GENERIC_INSUFFICIENT_FUNDS,
&mc->request.refresh.coin.denom_pub_hash,
&mc->request.refresh.coin.coin_pub));
- break;
-
+ return;
case MELT_ERROR_IDEMPOTENT_PLANCHET:
finish_loop (mc,
TALER_MHD_reply_with_error (
@@ -1470,8 +1443,7 @@ phase_generate_reply_error (
MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_PARAMETER_MALFORMED, /* FIXME: new error! */
"idempotent planchet"));
- break;
-
+ return;
case MELT_ERROR_NONCE_RESUSE:
finish_loop (mc,
TALER_MHD_reply_with_error (
@@ -1479,16 +1451,22 @@ phase_generate_reply_error (
MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_PARAMETER_MALFORMED, /* FIXME: new error */
"nonce reuse"));
- break;
-
+ return;
case MELT_ERROR_COIN_SIGNATURE_INVALID:
finish_loop (mc,
TALER_MHD_reply_with_ec (
mc->rc->connection,
TALER_EC_EXCHANGE_MELT_COIN_SIGNATURE_INVALID,
NULL));
- break;
+ return;
}
+ GNUNET_break (0);
+ finish_loop (mc,
+ TALER_MHD_reply_with_error (
+ mc->rc->connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
+ "error phase without error"));
}
diff --git a/src/exchange/taler-exchange-httpd_withdraw.c b/src/exchange/taler-exchange-httpd_withdraw.c
@@ -296,21 +296,21 @@ struct WithdrawContext
#define SET_ERROR(wc, ec) \
do \
{ GNUNET_static_assert (WITHDRAW_ERROR_NONE != ec); \
- (wc)->error.code = (ec); \
+ (wc)->error.code = (ec); \
(wc)->phase = WITHDRAW_PHASE_GENERATE_REPLY_ERROR; } while (0)
#define SET_ERROR_WITH_FIELD(wc, ec, field) \
do \
{ GNUNET_static_assert (WITHDRAW_ERROR_NONE != ec); \
- (wc)->error.code = (ec); \
- (wc)->error.details.field = (field); \
+ (wc)->error.code = (ec); \
+ (wc)->error.details.field = (field); \
(wc)->phase = WITHDRAW_PHASE_GENERATE_REPLY_ERROR; } while (0)
#define SET_ERROR_WITH_DETAIL(wc, ec, field, value) \
do \
{ GNUNET_static_assert (WITHDRAW_ERROR_NONE != ec); \
- (wc)->error.code = (ec); \
- (wc)->error.details.field = (value); \
+ (wc)->error.code = (ec); \
+ (wc)->error.details.field = (value); \
(wc)->phase = WITHDRAW_PHASE_GENERATE_REPLY_ERROR; } while (0)