aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2018-04-05 10:51:21 +0200
committerChristian Grothoff <christian@grothoff.org>2018-04-05 10:51:21 +0200
commitb46239b12f00e64888d4a8d35c019c850e740840 (patch)
tree0b234000846892d2216fbf433c2c650e8add8de4
parente248e97cbf0bf0d2f2f1870515de54c574f4b175 (diff)
use GNUNET_NZL instead of crazy hacks to ensure non-zero vararg array lengths
-rw-r--r--src/backenddb/plugin_merchantdb_postgres.c363
-rw-r--r--src/lib/merchant_api_pay.c20
2 files changed, 185 insertions, 198 deletions
diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c
index b6277183..c7427d77 100644
--- a/src/backenddb/plugin_merchantdb_postgres.c
+++ b/src/backenddb/plugin_merchantdb_postgres.c
@@ -2506,218 +2506,207 @@ process_deposits_for_refund_cb (void *cls,
unsigned int num_results)
{
struct InsertRefundContext *ctx = cls;
+ struct TALER_Amount current_refund;
+ struct TALER_Amount deposit_refund[GNUNET_NZL(num_results)];
+ struct TALER_CoinSpendPublicKeyP deposit_coin_pubs[GNUNET_NZL(num_results)];
+ struct TALER_Amount deposit_amount_with_fee[GNUNET_NZL(num_results)];
+ struct TALER_Amount deposit_refund_fee[GNUNET_NZL(num_results)];
- if (0 == num_results)
- {
- ctx->qs = GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
- /* We must return early here, or the zero-length variable size arrays below
- will be undefined behavior */
- return;
- }
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_get_zero (ctx->refund->currency,
+ &current_refund));
+ /* Pass 1: Collect amount of existing refunds into current_refund.
+ * Also store existing refunded amount for each deposit in deposit_refund. */
+
+ for (unsigned int i=0; i<num_results; i++)
{
- struct TALER_Amount current_refund;
- struct TALER_Amount deposit_refund[num_results];
- struct TALER_CoinSpendPublicKeyP deposit_coin_pubs[num_results];
- struct TALER_Amount deposit_amount_with_fee[num_results];
- struct TALER_Amount deposit_refund_fee[num_results];
+ struct TALER_CoinSpendPublicKeyP coin_pub;
+ struct TALER_Amount amount_with_fee;
+ struct TALER_Amount refund_fee;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
+ &coin_pub),
+ TALER_PQ_result_spec_amount ("amount_with_fee",
+ &amount_with_fee),
+ TALER_PQ_result_spec_amount ("refund_fee",
+ &refund_fee),
+ GNUNET_PQ_result_spec_end
+ };
- GNUNET_assert (GNUNET_OK ==
- TALER_amount_get_zero (ctx->refund->currency,
- &current_refund));
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
- /* Pass 1: Collect amount of existing refunds into current_refund.
- * Also store existing refunded amount for each deposit in deposit_refund. */
+ struct FindRefundContext ictx;
+ enum GNUNET_DB_QueryStatus ires;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (&coin_pub),
+ GNUNET_PQ_query_param_end
+ };
- for (unsigned int i=0; i<num_results; i++)
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_get_zero (ctx->refund->currency,
+ &ictx.refunded_amount));
+ ictx.err = GNUNET_OK; /* no error so far */
+ ires = GNUNET_PQ_eval_prepared_multi_select (ctx->pg->conn,
+ "find_refunds",
+ params,
+ &process_refund_cb,
+ &ictx);
+ if ( (GNUNET_OK != ictx.err) ||
+ (GNUNET_DB_STATUS_HARD_ERROR == ires) )
{
- struct TALER_CoinSpendPublicKeyP coin_pub;
- struct TALER_Amount amount_with_fee;
- struct TALER_Amount refund_fee;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
- &coin_pub),
- TALER_PQ_result_spec_amount ("amount_with_fee",
- &amount_with_fee),
- TALER_PQ_result_spec_amount ("refund_fee",
- &refund_fee),
- GNUNET_PQ_result_spec_end
- };
+ GNUNET_break (0);
+ ctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ if (GNUNET_DB_STATUS_SOFT_ERROR == ires)
+ {
+ ctx->qs = GNUNET_DB_STATUS_SOFT_ERROR;
+ return;
+ }
+ deposit_refund[i] = ictx.refunded_amount;
+ deposit_amount_with_fee[i] = amount_with_fee;
+ deposit_coin_pubs[i] = coin_pub;
+ deposit_refund_fee[i] = refund_fee;
+ if (GNUNET_SYSERR ==
+ TALER_amount_add (&current_refund,
+ &current_refund,
+ &ictx.refunded_amount))
+ {
+ GNUNET_break (0);
+ ctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Existing refund for coin %s is %s\n",
+ TALER_B2S (&coin_pub),
+ TALER_amount2s (&ictx.refunded_amount));
+ }
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
- return;
- }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Total existing refund is %s\n",
+ TALER_amount2s (&current_refund));
- struct FindRefundContext ictx;
- enum GNUNET_DB_QueryStatus ires;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (&coin_pub),
- GNUNET_PQ_query_param_end
- };
+ /* stop immediately if we are done */
+ if (0 >= TALER_amount_cmp (ctx->refund,
+ &current_refund))
+ {
+ ctx->qs = GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+ return;
+ }
- GNUNET_assert (GNUNET_OK ==
- TALER_amount_get_zero (ctx->refund->currency,
- &ictx.refunded_amount));
- ictx.err = GNUNET_OK; /* no error so far */
- ires = GNUNET_PQ_eval_prepared_multi_select (ctx->pg->conn,
- "find_refunds",
- params,
- &process_refund_cb,
- &ictx);
- if ( (GNUNET_OK != ictx.err) ||
- (GNUNET_DB_STATUS_HARD_ERROR == ires) )
- {
- GNUNET_break (0);
- ctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
- return;
- }
- if (GNUNET_DB_STATUS_SOFT_ERROR == ires)
- {
- ctx->qs = GNUNET_DB_STATUS_SOFT_ERROR;
- return;
- }
- deposit_refund[i] = ictx.refunded_amount;
- deposit_amount_with_fee[i] = amount_with_fee;
- deposit_coin_pubs[i] = coin_pub;
- deposit_refund_fee[i] = refund_fee;
- if (GNUNET_SYSERR ==
- TALER_amount_add (&current_refund,
- &current_refund,
- &ictx.refunded_amount))
- {
- GNUNET_break (0);
- ctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
- return;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Existing refund for coin %s is %s\n",
- TALER_B2S (&coin_pub),
- TALER_amount2s (&ictx.refunded_amount));
- }
+ /* Phase 2: Try to increase current refund until it matches desired refund */
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Total existing refund is %s\n",
- TALER_amount2s (&current_refund));
+ for (unsigned int i=0;i<num_results; i++)
+ {
+ const struct TALER_Amount *increment;
+ struct TALER_Amount left;
+ struct TALER_Amount remaining_refund;
- /* stop immediately if we are done */
- if (0 >= TALER_amount_cmp (ctx->refund,
- &current_refund))
+ /* How much of the coin is left after the existing refunds? */
+ if (GNUNET_SYSERR ==
+ TALER_amount_subtract (&left,
+ &deposit_amount_with_fee[i],
+ &deposit_refund[i]))
{
- ctx->qs = GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+ GNUNET_break (0);
+ ctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
return;
}
- /* Phase 2: Try to increase current refund until it matches desired refund */
-
- for (unsigned int i=0;i<num_results; i++)
+ if ( (0 == left.value) &&
+ (0 == left.fraction) )
{
- const struct TALER_Amount *increment;
- struct TALER_Amount left;
- struct TALER_Amount remaining_refund;
-
- /* How much of the coin is left after the existing refunds? */
- if (GNUNET_SYSERR ==
- TALER_amount_subtract (&left,
- &deposit_amount_with_fee[i],
- &deposit_refund[i]))
- {
- GNUNET_break (0);
- ctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
- return;
- }
-
- if ( (0 == left.value) &&
- (0 == left.fraction) )
- {
- /* coin was fully refunded, move to next coin */
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Coin %s fully refunded, moving to next coin\n",
- TALER_B2S (&deposit_coin_pubs[i]));
- continue;
- }
+ /* coin was fully refunded, move to next coin */
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Coin %s fully refunded, moving to next coin\n",
+ TALER_B2S (&deposit_coin_pubs[i]));
+ continue;
+ }
- /* How much of the refund is left? */
- if (GNUNET_SYSERR ==
- TALER_amount_subtract (&remaining_refund,
- ctx->refund,
- &current_refund))
- {
- GNUNET_break (0);
- ctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
- return;
- }
+ /* How much of the refund is left? */
+ if (GNUNET_SYSERR ==
+ TALER_amount_subtract (&remaining_refund,
+ ctx->refund,
+ &current_refund))
+ {
+ GNUNET_break (0);
+ ctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
- /* By how much will we increase the refund for this coin? */
- if (0 >= TALER_amount_cmp (&remaining_refund,
- &left))
- {
- /* remaining_refund <= left */
- increment = &remaining_refund;
- }
- else
- {
- increment = &left;
- }
+ /* By how much will we increase the refund for this coin? */
+ if (0 >= TALER_amount_cmp (&remaining_refund,
+ &left))
+ {
+ /* remaining_refund <= left */
+ increment = &remaining_refund;
+ }
+ else
+ {
+ increment = &left;
+ }
- if (GNUNET_SYSERR ==
- TALER_amount_add (&current_refund,
- &current_refund,
- increment))
- {
- GNUNET_break (0);
- ctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
- return;
- }
+ if (GNUNET_SYSERR ==
+ TALER_amount_add (&current_refund,
+ &current_refund,
+ increment))
+ {
+ GNUNET_break (0);
+ ctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
- /* actually run the refund */
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Coin %s deposit amount is %s\n",
- TALER_B2S (&deposit_coin_pubs[i]),
- TALER_amount2s (&deposit_amount_with_fee[i]));
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Coin %s refund will be incremented by %s\n",
- TALER_B2S (&deposit_coin_pubs[i]),
- TALER_amount2s (increment));
+ /* actually run the refund */
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Coin %s deposit amount is %s\n",
+ TALER_B2S (&deposit_coin_pubs[i]),
+ TALER_amount2s (&deposit_amount_with_fee[i]));
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Coin %s refund will be incremented by %s\n",
+ TALER_B2S (&deposit_coin_pubs[i]),
+ TALER_amount2s (increment));
+ {
+ enum GNUNET_DB_QueryStatus qs;
+
+ if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
+ (qs = insert_refund (ctx->pg,
+ ctx->merchant_pub,
+ ctx->h_contract_terms,
+ &deposit_coin_pubs[i],
+ ctx->reason,
+ increment,
+ &deposit_refund_fee[i])))
{
- enum GNUNET_DB_QueryStatus qs;
-
- if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
- (qs = insert_refund (ctx->pg,
- ctx->merchant_pub,
- ctx->h_contract_terms,
- &deposit_coin_pubs[i],
- ctx->reason,
- increment,
- &deposit_refund_fee[i])))
- {
- GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
- ctx->qs = qs;
- return;
- }
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+ ctx->qs = qs;
+ return;
}
- /* stop immediately if we are done */
- if (0 == TALER_amount_cmp (ctx->refund,
- &current_refund))
- return;
}
-
- /**
- * We end up here if nto all of the refund has been covered.
- * Although this should be checked as the business should never
- * issue a refund bigger than the contract's actual price, we cannot
- * rely upon the frontend being correct.
- */
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "The refund of %s is bigger than the order's value\n",
- TALER_amount2s (ctx->refund));
- ctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ /* stop immediately if we are done */
+ if (0 == TALER_amount_cmp (ctx->refund,
+ &current_refund))
+ return;
}
+
+ /**
+ * We end up here if nto all of the refund has been covered.
+ * Although this should be checked as the business should never
+ * issue a refund bigger than the contract's actual price, we cannot
+ * rely upon the frontend being correct.
+ */
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "The refund of %s is bigger than the order's value\n",
+ TALER_amount2s (ctx->refund));
+ ctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
}
diff --git a/src/lib/merchant_api_pay.c b/src/lib/merchant_api_pay.c
index b0a2f0e0..973a9b5e 100644
--- a/src/lib/merchant_api_pay.c
+++ b/src/lib/merchant_api_pay.c
@@ -76,7 +76,7 @@ struct TALER_MERCHANT_Pay
* Operational mode, either "pay" or "abort-refund".
*/
const char *mode;
-
+
/**
* Reference to the execution context.
*/
@@ -96,7 +96,7 @@ struct TALER_MERCHANT_Pay
* Hash of the contract, only available in "abort-refund" mode.
*/
struct GNUNET_HashCode h_contract_terms;
-
+
};
@@ -132,9 +132,7 @@ check_abort_refund (struct TALER_MERCHANT_Pay *ph,
}
num_refunds = json_array_size (refunds);
{
- /* The "+ 1" is necessary since num_refunds might be 0, and variable size arrays must
- * be >0, or it's undefined behavior */
- struct TALER_MERCHANT_RefundEntry res[num_refunds + 1];
+ struct TALER_MERCHANT_RefundEntry res[GNUNET_NZL(num_refunds)];
for (unsigned int i=0;i<num_refunds;i++)
{
@@ -166,7 +164,7 @@ check_abort_refund (struct TALER_MERCHANT_Pay *ph,
rr.purpose.size = htonl (sizeof (struct TALER_RefundRequestPS));
rr.h_contract_terms = ph->h_contract_terms;
rr.coin_pub = res[i].coin_pub;
- rr.merchant = merchant_pub;
+ rr.merchant = merchant_pub;
rr.rtransaction_id = GNUNET_htonll (res[i].rtransaction_id);
found = -1;
for (unsigned int j=0;j<ph->num_coins;j++)
@@ -373,7 +371,7 @@ handle_pay_finished (void *cls,
GNUNET_break (0);
response_code = 0;
break;
- }
+ }
ph->pay_cb (ph->pay_cb_cls,
response_code,
TALER_JSON_get_error_code (json),
@@ -383,7 +381,7 @@ handle_pay_finished (void *cls,
{
GNUNET_assert (0 == strcasecmp (ph->mode,
"abort-refund"));
-
+
switch (response_code)
{
case 0:
@@ -425,7 +423,7 @@ handle_pay_finished (void *cls,
GNUNET_break (0);
response_code = 0;
break;
- }
+ }
ph->abort_cb (ph->abort_cb_cls,
response_code,
TALER_JSON_get_error_code (json),
@@ -435,7 +433,7 @@ handle_pay_finished (void *cls,
NULL,
json);
}
-
+
TALER_MERCHANT_pay_cancel (ph);
}
@@ -660,7 +658,7 @@ prepare_pay_generic (struct GNUNET_CURL_Context *ctx,
GNUNET_break (0);
return NULL;
}
-
+
dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT);
dr.purpose.size = htonl (sizeof (struct TALER_DepositRequestPS));
dr.h_contract_terms = *h_contract_terms;