exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

commit 34d7bb7e02ad0180d1e8db920873af24ebb24a7c
parent 1c3ce9f40c6c29252ffdd27d7295f1628d0a10be
Author: Christian Grothoff <christian@grothoff.org>
Date:   Sun,  9 Aug 2026 13:10:38 +0200

db: handle INT64_MIN negation and cap the rows returned per query

Negating the signed limit is undefined for INT64_MIN and the wrapped
value reached Postgres as a negative LIMIT; the added per-file
MAX_RECORDS cap bounds the result set even for an unclamped caller.

Diffstat:
Msrc/auditordb/iterate_amount_arithmetic_inconsistencies.c | 11++++++++++-
Msrc/auditordb/iterate_auditor_aml_holds.c | 10+++++++++-
Msrc/auditordb/iterate_auditor_closure_lags.c | 10+++++++++-
Msrc/auditordb/iterate_bad_sig_losses.c | 10+++++++++-
Msrc/auditordb/iterate_coin_inconsistencies.c | 11++++++++++-
Msrc/auditordb/iterate_denomination_key_validity_withdraw_inconsistencies.c | 10+++++++++-
Msrc/auditordb/iterate_denomination_pending.c | 10+++++++++-
Msrc/auditordb/iterate_denominations_without_sigs.c | 10+++++++++-
Msrc/auditordb/iterate_deposit_confirmations.c | 10+++++++++-
Msrc/auditordb/iterate_early_aggregations.c | 10+++++++++-
Msrc/auditordb/iterate_emergencies.c | 11++++++++++-
Msrc/auditordb/iterate_emergencies_by_count.c | 10+++++++++-
Msrc/auditordb/iterate_exchange_signkeys.c | 10+++++++++-
Msrc/auditordb/iterate_fee_time_inconsistencies.c | 10+++++++++-
Msrc/auditordb/iterate_historic_denom_revenue.c | 10+++++++++-
Msrc/auditordb/iterate_historic_reserve_revenue.c | 10+++++++++-
Msrc/auditordb/iterate_kycauth_in_inconsistencies.c | 10+++++++++-
Msrc/auditordb/iterate_misattribution_in_inconsistencies.c | 10+++++++++-
Msrc/auditordb/iterate_pending_deposits.c | 10+++++++++-
Msrc/auditordb/iterate_purse_not_closed_inconsistencies.c | 10+++++++++-
Msrc/auditordb/iterate_purses.c | 10+++++++++-
Msrc/auditordb/iterate_reserve_balance_insufficient_inconsistencies.c | 10+++++++++-
Msrc/auditordb/iterate_reserve_balance_summary_wrong_inconsistencies.c | 10+++++++++-
Msrc/auditordb/iterate_reserve_in_inconsistencies.c | 10+++++++++-
Msrc/auditordb/iterate_reserve_not_closed_inconsistencies.c | 10+++++++++-
Msrc/auditordb/iterate_reserves.c | 10+++++++++-
Msrc/auditordb/iterate_row_inconsistencies.c | 11++++++++++-
Msrc/auditordb/iterate_row_minor_inconsistencies.c | 10+++++++++-
Msrc/auditordb/iterate_wire_format_inconsistencies.c | 10+++++++++-
Msrc/auditordb/iterate_wire_out_inconsistencies.c | 10+++++++++-
Msrc/exchangedb/helper.h | 24++++++++++++++++++++++++
Msrc/exchangedb/iterate_aml_attributes.c | 10+++++++++-
Msrc/exchangedb/iterate_aml_decisions.c | 10+++++++++-
Msrc/exchangedb/iterate_aml_history.c | 10+++++++++-
Msrc/exchangedb/iterate_aml_measures.c | 10+++++++++-
Msrc/exchangedb/iterate_exchange_credit_transfers.c | 11++++++++++-
Msrc/exchangedb/iterate_exchange_debit_transfers.c | 10+++++++++-
Msrc/exchangedb/iterate_exchange_kycauth_transfers.c | 11++++++++++-
Msrc/exchangedb/iterate_kyc_accounts.c | 10+++++++++-
Msrc/exchangedb/iterate_wallet_merges.c | 11++++++++++-
40 files changed, 382 insertions(+), 39 deletions(-)

diff --git a/src/auditordb/iterate_amount_arithmetic_inconsistencies.c b/src/auditordb/iterate_amount_arithmetic_inconsistencies.c @@ -18,6 +18,14 @@ #include "pg_helper.h" #include "auditor-database/iterate_amount_arithmetic_inconsistencies.h" + +/** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + /** * Closure for #deposit_confirmation_cb(). */ @@ -113,7 +121,8 @@ TALER_AUDITORDB_iterate_amount_arithmetic_inconsistencies ( TALER_AUDITORDB_AmountArithmeticInconsistencyCallback cb, void *cb_cls) { - uint64_t plimit = TALER_AUDITORDB_abs_limit (limit); + uint64_t plimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_AUDITORDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&offset), GNUNET_PQ_query_param_bool (return_suppressed), diff --git a/src/auditordb/iterate_auditor_aml_holds.c b/src/auditordb/iterate_auditor_aml_holds.c @@ -24,6 +24,13 @@ /** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + +/** * Closure for #auditor_aml_holds_cb(). */ struct AuditorAmlHoldsContext @@ -121,7 +128,8 @@ TALER_AUDITORDB_iterate_auditor_aml_holds ( TALER_AUDITORDB_AuditorAmlHoldCallback cb, TALER_AUDITORDB_AUDITOR_AML_HOLD_RESULT_CLOSURE *cb_cls) { - uint64_t plimit = TALER_AUDITORDB_abs_limit (limit); + uint64_t plimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_AUDITORDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&offset), GNUNET_PQ_query_param_bool (return_suppressed), diff --git a/src/auditordb/iterate_auditor_closure_lags.c b/src/auditordb/iterate_auditor_closure_lags.c @@ -20,6 +20,13 @@ #include "auditor-database/iterate_auditor_closure_lags.h" +/** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + struct ClosureLagsContext { @@ -112,7 +119,8 @@ TALER_AUDITORDB_iterate_auditor_closure_lags ( TALER_AUDITORDB_ClosureLagsCallback cb, void *cb_cls) { - uint64_t plimit = TALER_AUDITORDB_abs_limit (limit); + uint64_t plimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_AUDITORDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&offset), GNUNET_PQ_query_param_bool (return_suppressed), diff --git a/src/auditordb/iterate_bad_sig_losses.c b/src/auditordb/iterate_bad_sig_losses.c @@ -19,6 +19,13 @@ #include "auditor-database/iterate_bad_sig_losses.h" +/** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + struct BadSigLossesContext { @@ -111,7 +118,8 @@ TALER_AUDITORDB_iterate_bad_sig_losses ( TALER_AUDITORDB_BadSigLossesCallback cb, void *cb_cls) { - uint64_t plimit = TALER_AUDITORDB_abs_limit (limit); + uint64_t plimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_AUDITORDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&offset), GNUNET_PQ_query_param_bool (return_suppressed), diff --git a/src/auditordb/iterate_coin_inconsistencies.c b/src/auditordb/iterate_coin_inconsistencies.c @@ -20,6 +20,14 @@ #include "pg_helper.h" #include "auditor-database/iterate_coin_inconsistencies.h" + +/** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + /** * Closure for #deposit_confirmation_cb(). */ @@ -121,7 +129,8 @@ TALER_AUDITORDB_iterate_coin_inconsistencies ( void *cb_cls) { - uint64_t plimit = TALER_AUDITORDB_abs_limit (limit); + uint64_t plimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_AUDITORDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&offset), GNUNET_PQ_query_param_bool (return_suppressed), diff --git a/src/auditordb/iterate_denomination_key_validity_withdraw_inconsistencies.c b/src/auditordb/iterate_denomination_key_validity_withdraw_inconsistencies.c @@ -20,6 +20,13 @@ /** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + +/** * Closure for #denomination_key_validity_withdraw_inconsistency_cb(). */ struct DenominationKeyValidityWithdrawInconsistencyContext @@ -112,7 +119,8 @@ TALER_AUDITORDB_iterate_denomination_key_validity_withdraw_inconsistencies ( TALER_AUDITORDB_DenominationKeyValidityWithdrawInconsistencyCallback cb, void *cb_cls) { - uint64_t plimit = TALER_AUDITORDB_abs_limit (limit); + uint64_t plimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_AUDITORDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&offset), GNUNET_PQ_query_param_bool (return_suppressed), diff --git a/src/auditordb/iterate_denomination_pending.c b/src/auditordb/iterate_denomination_pending.c @@ -18,6 +18,13 @@ #include "auditor-database/iterate_denomination_pending.h" +/** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + struct DenominationPendingContext { @@ -111,7 +118,8 @@ TALER_AUDITORDB_iterate_denomination_pending ( TALER_AUDITORDB_DenominationPendingCallback cb, void *cb_cls) { - uint64_t plimit = TALER_AUDITORDB_abs_limit (limit); + uint64_t plimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_AUDITORDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&offset), GNUNET_PQ_query_param_uint64 (&plimit), diff --git a/src/auditordb/iterate_denominations_without_sigs.c b/src/auditordb/iterate_denominations_without_sigs.c @@ -19,6 +19,13 @@ #include "auditor-database/iterate_denominations_without_sigs.h" +/** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + struct DenominationsWithoutSigsContext { @@ -111,7 +118,8 @@ TALER_AUDITORDB_iterate_denominations_without_sigs ( TALER_AUDITORDB_DenominationsWithoutSigsCallback cb, void *cb_cls) { - uint64_t plimit = TALER_AUDITORDB_abs_limit (limit); + uint64_t plimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_AUDITORDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&offset), GNUNET_PQ_query_param_bool (return_suppressed), diff --git a/src/auditordb/iterate_deposit_confirmations.c b/src/auditordb/iterate_deposit_confirmations.c @@ -25,6 +25,13 @@ /** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + +/** * Closure for #deposit_confirmation_cb(). */ struct DepositConfirmationContext @@ -153,7 +160,8 @@ TALER_AUDITORDB_iterate_deposit_confirmations ( TALER_AUDITORDB_DepositConfirmationCallback cb, void *cb_cls) { - uint64_t plimit = TALER_AUDITORDB_abs_limit (limit); + uint64_t plimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_AUDITORDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&offset), GNUNET_PQ_query_param_bool (return_suppressed), diff --git a/src/auditordb/iterate_early_aggregations.c b/src/auditordb/iterate_early_aggregations.c @@ -25,6 +25,13 @@ /** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + +/** * Closure for #early_aggregation_cb(). */ struct EarlyAggregationContext @@ -116,7 +123,8 @@ TALER_AUDITORDB_iterate_early_aggregations (struct cb, void *cb_cls) { - uint64_t ulimit = TALER_AUDITORDB_abs_limit (limit); + uint64_t ulimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_AUDITORDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&offset), GNUNET_PQ_query_param_uint64 (&ulimit), diff --git a/src/auditordb/iterate_emergencies.c b/src/auditordb/iterate_emergencies.c @@ -18,6 +18,14 @@ #include "pg_helper.h" #include "auditor-database/iterate_emergencies.h" + +/** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + /** * Closure for #emergency_cb(). */ @@ -114,7 +122,8 @@ TALER_AUDITORDB_iterate_emergencies (struct TALER_AUDITORDB_PostgresContext *pg, TALER_AUDITORDB_EmergencyCallback cb, void *cb_cls) { - uint64_t plimit = TALER_AUDITORDB_abs_limit (limit); + uint64_t plimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_AUDITORDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&offset), GNUNET_PQ_query_param_bool (return_suppressed), diff --git a/src/auditordb/iterate_emergencies_by_count.c b/src/auditordb/iterate_emergencies_by_count.c @@ -20,6 +20,13 @@ /** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + +/** * Closure for #emergency_cb(). */ struct EmergencyByCountContext @@ -120,7 +127,8 @@ TALER_AUDITORDB_iterate_emergencies_by_count (struct cb, void *cb_cls) { - uint64_t plimit = TALER_AUDITORDB_abs_limit (limit); + uint64_t plimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_AUDITORDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&offset), GNUNET_PQ_query_param_bool (return_suppressed), diff --git a/src/auditordb/iterate_exchange_signkeys.c b/src/auditordb/iterate_exchange_signkeys.c @@ -21,6 +21,13 @@ #include "auditor-database/iterate_exchange_signkeys.h" +/** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + struct ExchangeSignkeysContext { @@ -114,7 +121,8 @@ TALER_AUDITORDB_iterate_exchange_signkeys ( TALER_AUDITORDB_ExchangeSignkeysCallback cb, void *cb_cls) { - uint64_t plimit = TALER_AUDITORDB_abs_limit (limit); + uint64_t plimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_AUDITORDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&offset), GNUNET_PQ_query_param_uint64 (&plimit), diff --git a/src/auditordb/iterate_fee_time_inconsistencies.c b/src/auditordb/iterate_fee_time_inconsistencies.c @@ -19,6 +19,13 @@ /** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + +/** * Closure for #feetimeinconsistency_cb(). */ struct FeeTimeInconsistencyContext @@ -107,7 +114,8 @@ TALER_AUDITORDB_iterate_fee_time_inconsistencies ( TALER_AUDITORDB_FeeTimeInconsistencyCallback cb, void *cb_cls) { - uint64_t plimit = TALER_AUDITORDB_abs_limit (limit); + uint64_t plimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_AUDITORDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&offset), GNUNET_PQ_query_param_bool (return_suppressed), diff --git a/src/auditordb/iterate_historic_denom_revenue.c b/src/auditordb/iterate_historic_denom_revenue.c @@ -24,6 +24,13 @@ /** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + +/** * Closure for #historic_denom_revenue_cb(). */ struct HistoricDenomRevenueContext @@ -119,7 +126,8 @@ TALER_AUDITORDB_iterate_historic_denom_revenue ( TALER_AUDITORDB_HistoricDenominationRevenueDataCallback cb, void *cb_cls) { - uint64_t ulimit = TALER_AUDITORDB_abs_limit (limit); + uint64_t ulimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_AUDITORDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&offset), GNUNET_PQ_query_param_uint64 (&ulimit), diff --git a/src/auditordb/iterate_historic_reserve_revenue.c b/src/auditordb/iterate_historic_reserve_revenue.c @@ -24,6 +24,13 @@ /** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + +/** * Closure for #historic_reserve_revenue_cb(). */ struct HistoricReserveRevenueContext @@ -114,7 +121,8 @@ TALER_AUDITORDB_iterate_historic_reserve_revenue ( TALER_AUDITORDB_HistoricReserveRevenueDataCallback cb, void *cb_cls) { - uint64_t ulimit = TALER_AUDITORDB_abs_limit (limit); + uint64_t ulimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_AUDITORDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&offset), GNUNET_PQ_query_param_uint64 (&ulimit), diff --git a/src/auditordb/iterate_kycauth_in_inconsistencies.c b/src/auditordb/iterate_kycauth_in_inconsistencies.c @@ -25,6 +25,13 @@ #include "auditor-database/iterate_kycauth_in_inconsistencies.h" +/** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + struct KycauthInInconsistencyContext { @@ -122,7 +129,8 @@ TALER_AUDITORDB_iterate_kycauth_in_inconsistencies ( TALER_AUDITORDB_KycauthInInconsistencyCallback cb, void *cb_cls) { - uint64_t plimit = TALER_AUDITORDB_abs_limit (limit); + uint64_t plimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_AUDITORDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&offset), GNUNET_PQ_query_param_bool (return_suppressed), diff --git a/src/auditordb/iterate_misattribution_in_inconsistencies.c b/src/auditordb/iterate_misattribution_in_inconsistencies.c @@ -21,6 +21,13 @@ #include "auditor-database/iterate_misattribution_in_inconsistencies.h" +/** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + struct MisattributionInInconsistencyContext { @@ -112,7 +119,8 @@ TALER_AUDITORDB_iterate_misattribution_in_inconsistencies (struct cb, void *cb_cls) { - uint64_t plimit = TALER_AUDITORDB_abs_limit (limit); + uint64_t plimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_AUDITORDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&offset), GNUNET_PQ_query_param_bool (return_suppressed), diff --git a/src/auditordb/iterate_pending_deposits.c b/src/auditordb/iterate_pending_deposits.c @@ -24,6 +24,13 @@ /** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + +/** * Closure for #wire_missing_cb(). */ struct WireMissingContext @@ -124,7 +131,8 @@ TALER_AUDITORDB_iterate_pending_deposits (struct , void *cb_cls) { - uint64_t ulimit = TALER_AUDITORDB_abs_limit (limit); + uint64_t ulimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_AUDITORDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_absolute_time (&deadline), GNUNET_PQ_query_param_uint64 (&offset), diff --git a/src/auditordb/iterate_purse_not_closed_inconsistencies.c b/src/auditordb/iterate_purse_not_closed_inconsistencies.c @@ -19,6 +19,13 @@ /** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + +/** * Closure for #purse_not_closed_inconsistencies_cb(). */ struct PurseNotClosedInconsistenciesContext @@ -112,7 +119,8 @@ TALER_AUDITORDB_iterate_purse_not_closed_inconsistencies (struct cb, void *cb_cls) { - uint64_t plimit = TALER_AUDITORDB_abs_limit (limit); + uint64_t plimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_AUDITORDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&offset), GNUNET_PQ_query_param_bool (return_suppressed), diff --git a/src/auditordb/iterate_purses.c b/src/auditordb/iterate_purses.c @@ -18,6 +18,13 @@ #include "auditor-database/iterate_purses.h" +/** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + struct PursesContext { @@ -105,7 +112,8 @@ TALER_AUDITORDB_iterate_purses (struct TALER_AUDITORDB_PostgresContext *pg, TALER_AUDITORDB_PursesCallback cb, void *cb_cls) { - uint64_t plimit = TALER_AUDITORDB_abs_limit (limit); + uint64_t plimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_AUDITORDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&offset), GNUNET_PQ_query_param_uint64 (&plimit), diff --git a/src/auditordb/iterate_reserve_balance_insufficient_inconsistencies.c b/src/auditordb/iterate_reserve_balance_insufficient_inconsistencies.c @@ -20,6 +20,13 @@ /** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + +/** * Closure for #reserve_balance_insufficient_inconsistency_cb(). */ struct ReserveBalanceInsufficientInconsistencyContext @@ -117,7 +124,8 @@ TALER_AUDITORDB_iterate_reserve_balance_insufficient_inconsistencies (struct void * cb_cls) { - uint64_t plimit = TALER_AUDITORDB_abs_limit (limit); + uint64_t plimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_AUDITORDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&offset), GNUNET_PQ_query_param_bool (return_suppressed), diff --git a/src/auditordb/iterate_reserve_balance_summary_wrong_inconsistencies.c b/src/auditordb/iterate_reserve_balance_summary_wrong_inconsistencies.c @@ -19,6 +19,13 @@ "auditor-database/iterate_reserve_balance_summary_wrong_inconsistencies.h" +/** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + struct ReserveBalanceSummaryWrongInconsistencyContext { @@ -114,7 +121,8 @@ TALER_AUDITORDB_iterate_reserve_balance_summary_wrong_inconsistencies (struct void * cb_cls) { - uint64_t plimit = TALER_AUDITORDB_abs_limit (limit); + uint64_t plimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_AUDITORDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&offset), GNUNET_PQ_query_param_bool (return_suppressed), diff --git a/src/auditordb/iterate_reserve_in_inconsistencies.c b/src/auditordb/iterate_reserve_in_inconsistencies.c @@ -20,6 +20,13 @@ #include "auditor-database/iterate_reserve_in_inconsistencies.h" +/** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + struct ReserveInInconsistencyContext { @@ -120,7 +127,8 @@ TALER_AUDITORDB_iterate_reserve_in_inconsistencies (struct cb, void *cb_cls) { - uint64_t plimit = TALER_AUDITORDB_abs_limit (limit); + uint64_t plimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_AUDITORDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&offset), GNUNET_PQ_query_param_bool (return_suppressed), diff --git a/src/auditordb/iterate_reserve_not_closed_inconsistencies.c b/src/auditordb/iterate_reserve_not_closed_inconsistencies.c @@ -18,6 +18,13 @@ #include "auditor-database/iterate_reserve_not_closed_inconsistencies.h" +/** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + struct ReserveNotClosedInconsistencyContext { @@ -111,7 +118,8 @@ TALER_AUDITORDB_iterate_reserve_not_closed_inconsistencies (struct cb, void *cb_cls) { - uint64_t plimit = TALER_AUDITORDB_abs_limit (limit); + uint64_t plimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_AUDITORDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&offset), GNUNET_PQ_query_param_bool (return_suppressed), diff --git a/src/auditordb/iterate_reserves.c b/src/auditordb/iterate_reserves.c @@ -18,6 +18,13 @@ #include "auditor-database/iterate_reserves.h" +/** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + struct ReservesContext { @@ -120,7 +127,8 @@ TALER_AUDITORDB_iterate_reserves (struct TALER_AUDITORDB_PostgresContext *pg, TALER_AUDITORDB_ReservesCallback cb, void *cb_cls) { - uint64_t plimit = TALER_AUDITORDB_abs_limit (limit); + uint64_t plimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_AUDITORDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&offset), GNUNET_PQ_query_param_uint64 (&plimit), diff --git a/src/auditordb/iterate_row_inconsistencies.c b/src/auditordb/iterate_row_inconsistencies.c @@ -18,6 +18,14 @@ #include "pg_helper.h" #include "auditor-database/iterate_row_inconsistencies.h" + +/** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + /** * Closure for #deposit_confirmation_cb(). */ @@ -113,7 +121,8 @@ TALER_AUDITORDB_iterate_row_inconsistencies ( void *cb_cls) { - uint64_t plimit = TALER_AUDITORDB_abs_limit (limit); + uint64_t plimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_AUDITORDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&offset), GNUNET_PQ_query_param_bool (return_suppressed), diff --git a/src/auditordb/iterate_row_minor_inconsistencies.c b/src/auditordb/iterate_row_minor_inconsistencies.c @@ -18,6 +18,13 @@ #include "auditor-database/iterate_row_minor_inconsistencies.h" +/** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + struct RowMinorInconsistenciesContext { @@ -105,7 +112,8 @@ TALER_AUDITORDB_iterate_row_minor_inconsistencies ( TALER_AUDITORDB_RowMinorInconsistenciesCallback cb, void *cb_cls) { - uint64_t plimit = TALER_AUDITORDB_abs_limit (limit); + uint64_t plimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_AUDITORDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&offset), GNUNET_PQ_query_param_bool (return_suppressed), diff --git a/src/auditordb/iterate_wire_format_inconsistencies.c b/src/auditordb/iterate_wire_format_inconsistencies.c @@ -18,6 +18,13 @@ #include "auditor-database/iterate_wire_format_inconsistencies.h" +/** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + struct WireFormatInconsistencyContext { @@ -109,7 +116,8 @@ TALER_AUDITORDB_iterate_wire_format_inconsistencies (struct cb, void *cb_cls) { - uint64_t plimit = TALER_AUDITORDB_abs_limit (limit); + uint64_t plimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_AUDITORDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&offset), GNUNET_PQ_query_param_bool (return_suppressed), diff --git a/src/auditordb/iterate_wire_out_inconsistencies.c b/src/auditordb/iterate_wire_out_inconsistencies.c @@ -18,6 +18,13 @@ #include "auditor-database/iterate_wire_out_inconsistencies.h" +/** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + struct WireOutInconsistencyContext { @@ -110,7 +117,8 @@ TALER_AUDITORDB_iterate_wire_out_inconsistencies ( TALER_AUDITORDB_WireOutInconsistencyCallback cb, void *cb_cls) { - uint64_t plimit = TALER_AUDITORDB_abs_limit (limit); + uint64_t plimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_AUDITORDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&offset), GNUNET_PQ_query_param_bool (return_suppressed), diff --git a/src/exchangedb/helper.h b/src/exchangedb/helper.h @@ -104,6 +104,30 @@ extern unsigned long long TEH_PG_prep_gen_; /** + * Convert the signed @a limit of a paginated listing into the row + * limit to pass to SQL. The sign selects the iteration direction and + * the magnitude the number of rows, but computing `-limit` directly is + * undefined behaviour for `INT64_MIN`, and the resulting value would + * reach Postgres as `LIMIT -9223372036854775808`, which errors out. + * `INT64_MIN` is therefore saturated to `INT64_MAX`. + * + * @param limit signed limit as given by the caller + * @return absolute value of @a limit, without signed overflow + */ +static inline uint64_t +TALER_EXCHANGEDB_abs_limit (int64_t limit) +{ + /* Postgres binds INT8 as a *signed* 64-bit integer, so a magnitude + above INT64_MAX would reach LIMIT as a negative number. */ + if (INT64_MIN == limit) + return (uint64_t) INT64_MAX; + if (limit < 0) + return (uint64_t) -limit; + return (uint64_t) limit; +} + + +/** * Prepares SQL statement @a sql under @a name for * connection @a pg once. * Returns with #GNUNET_DB_STATUS_HARD_ERROR on failure. diff --git a/src/exchangedb/iterate_aml_attributes.c b/src/exchangedb/iterate_aml_attributes.c @@ -24,6 +24,13 @@ /** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + +/** * Closure for #handle_aml_result. */ struct AmlAttributeResultContext @@ -122,7 +129,8 @@ TALER_EXCHANGEDB_iterate_aml_attributes ( TALER_EXCHANGEDB_AmlAttributeCallback cb, void *cb_cls) { - uint64_t ulimit = (limit > 0) ? limit : -limit; + uint64_t ulimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_EXCHANGEDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_auto_from_type (h_payto), GNUNET_PQ_query_param_uint64 (&offset), diff --git a/src/exchangedb/iterate_aml_decisions.c b/src/exchangedb/iterate_aml_decisions.c @@ -25,6 +25,13 @@ /** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + +/** * Closure for #handle_aml_result. */ struct AmlProcessResultContext @@ -168,7 +175,8 @@ TALER_EXCHANGEDB_iterate_aml_decisions ( TALER_EXCHANGEDB_AmlDecisionCallback cb, void *cb_cls) { - uint64_t ulimit = (limit > 0) ? limit : -limit; + uint64_t ulimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_EXCHANGEDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_bool (NULL == h_payto), NULL == h_payto diff --git a/src/exchangedb/iterate_aml_history.c b/src/exchangedb/iterate_aml_history.c @@ -24,6 +24,13 @@ /** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + +/** * Closure for callbacks called from #TALER_EXCHANGEDB_iterate_aml_history() */ struct AmlHistoryContext @@ -136,7 +143,8 @@ TALER_EXCHANGEDB_iterate_aml_history ( .cb = cb, .cb_cls = cb_cls }; - uint64_t ulimit = (limit < 0) ? (-limit) : limit; + uint64_t ulimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_EXCHANGEDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_auto_from_type (h_payto), GNUNET_PQ_query_param_uint64 (&offset), diff --git a/src/exchangedb/iterate_aml_measures.c b/src/exchangedb/iterate_aml_measures.c @@ -24,6 +24,13 @@ /** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + +/** * Closure for #handle_aml_result. */ struct LegiMeasureResultContext @@ -117,7 +124,8 @@ TALER_EXCHANGEDB_iterate_aml_measures ( TALER_EXCHANGEDB_LegitimizationMeasureCallback cb, void *cb_cls) { - uint64_t ulimit = (limit > 0) ? limit : -limit; + uint64_t ulimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_EXCHANGEDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_bool (NULL == h_payto), NULL == h_payto diff --git a/src/exchangedb/iterate_exchange_credit_transfers.c b/src/exchangedb/iterate_exchange_credit_transfers.c @@ -22,6 +22,14 @@ #include "exchange-database/iterate_exchange_credit_transfers.h" #include "helper.h" + +/** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + /** * Closure for #handle_aml_result. */ @@ -119,7 +127,8 @@ TALER_EXCHANGEDB_iterate_exchange_credit_transfers ( .cb_cls = cb_cls, .status = GNUNET_OK }; - uint64_t ulimit = (limit > 0) ? limit : -limit; + uint64_t ulimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_EXCHANGEDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&offset), GNUNET_PQ_query_param_uint64 (&ulimit), diff --git a/src/exchangedb/iterate_exchange_debit_transfers.c b/src/exchangedb/iterate_exchange_debit_transfers.c @@ -24,6 +24,13 @@ /** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + +/** * Closure for #handle_aml_result. */ struct SelectTransferContext @@ -120,7 +127,8 @@ TALER_EXCHANGEDB_iterate_exchange_debit_transfers ( .cb_cls = cb_cls, .status = GNUNET_OK }; - uint64_t ulimit = (limit > 0) ? limit : -limit; + uint64_t ulimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_EXCHANGEDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&offset), GNUNET_PQ_query_param_uint64 (&ulimit), diff --git a/src/exchangedb/iterate_exchange_kycauth_transfers.c b/src/exchangedb/iterate_exchange_kycauth_transfers.c @@ -22,6 +22,14 @@ #include "exchange-database/iterate_exchange_kycauth_transfers.h" #include "helper.h" + +/** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + /** * Closure for #handle_aml_result. */ @@ -119,7 +127,8 @@ TALER_EXCHANGEDB_iterate_exchange_kycauth_transfers ( .cb_cls = cb_cls, .status = GNUNET_OK }; - uint64_t ulimit = (limit > 0) ? limit : -limit; + uint64_t ulimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_EXCHANGEDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&offset), GNUNET_PQ_query_param_uint64 (&ulimit), diff --git a/src/exchangedb/iterate_kyc_accounts.c b/src/exchangedb/iterate_kyc_accounts.c @@ -24,6 +24,13 @@ /** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + +/** * Closure for #handle_aml_result. */ struct KycAccountResultContext @@ -138,7 +145,8 @@ TALER_EXCHANGEDB_iterate_kyc_accounts ( TALER_EXCHANGEDB_AmlAccountListCallback cb, void *cb_cls) { - uint64_t ulimit = (limit > 0) ? limit : -limit; + uint64_t ulimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_EXCHANGEDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&offset), GNUNET_PQ_query_param_uint64 (&ulimit), diff --git a/src/exchangedb/iterate_wallet_merges.c b/src/exchangedb/iterate_wallet_merges.c @@ -22,6 +22,14 @@ #include "exchange-database/iterate_wallet_merges.h" #include "helper.h" + +/** + * Hard upper bound on the number of records returned by a single + * call, regardless of the limit requested by the client. + */ +#define MAX_RECORDS 50000 + + /** * Closure for #handle_aml_result. */ @@ -119,7 +127,8 @@ TALER_EXCHANGEDB_iterate_wallet_merges ( .cb_cls = cb_cls, .status = GNUNET_OK }; - uint64_t ulimit = (limit > 0) ? limit : -limit; + uint64_t ulimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, + TALER_EXCHANGEDB_abs_limit (limit)); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&offset), GNUNET_PQ_query_param_uint64 (&ulimit),