commit 8d3c6d195052b7cc24d4b5688b72ed6b6b944ff7
parent 2e4e10f0e19b8140f48a0a79c91419a2204d188c
Author: Christian Grothoff <christian@grothoff.org>
Date: Wed, 20 May 2026 22:39:26 +0200
improve input validation for data from merchant backend
Diffstat:
1 file changed, 33 insertions(+), 15 deletions(-)
diff --git a/src/TalerMerchantApiService.php b/src/TalerMerchantApiService.php
@@ -436,24 +436,42 @@ class TalerMerchantApiService {
$result = $base;
$now = time();
foreach ($r->data['token_families'] as $family) {
- $valid_before = ($family['valid_before']['t_s'] === 'never')
+ // Defensively skip malformed entries rather than dereferencing
+ // missing keys (which would emit PHP warnings and could yield
+ // bogus comparisons).
+ $slug = $family['slug'] ?? NULL;
+ if (!is_string($slug) || $slug === '') {
+ $this->logger->warning('Token family entry without a usable slug, skipping it.');
+ continue;
+ }
+ if (($family['kind'] ?? NULL) !== 'subscription') {
+ $this->logger->info('Token family @slug is not a subscription, skipping it.', ['@slug' => $slug]);
+ continue;
+ }
+ $valid_after_raw = $family['valid_after']['t_s'] ?? NULL;
+ $valid_before_raw = $family['valid_before']['t_s'] ?? NULL;
+ if (!is_int($valid_after_raw) || $valid_before_raw === NULL) {
+ $this->logger->warning('Token family @slug has malformed validity window, skipping it.', ['@slug' => $slug]);
+ continue;
+ }
+ $valid_before = ($valid_before_raw === 'never')
? PHP_INT_MAX
- : $family['valid_before']['t_s'];
- if (($family['kind'] === 'subscription') &&
- ($family['valid_after']['t_s'] < $now) &&
- ($valid_before >= $now)) {
- $slug = $family['slug'];
- $result[$slug] = [
- 'name' => $family['name'],
- 'label' => $slug,
- 'valid_before_s' => $valid_before,
- 'description' => $family['description'],
- 'description_i18n' => ($family['description_i18n'] ?? NULL),
- ];
+ : (is_int($valid_before_raw) ? $valid_before_raw : NULL);
+ if ($valid_before === NULL) {
+ $this->logger->warning('Token family @slug has non-integer valid_before, skipping it.', ['@slug' => $slug]);
+ continue;
}
- else {
- $this->logger->info('Token family @slug is not valid right now, skipping it.', ['@slug' => $family['slug']]);
+ if (!($valid_after_raw < $now && $valid_before >= $now)) {
+ $this->logger->info('Token family @slug is not valid right now, skipping it.', ['@slug' => $slug]);
+ continue;
}
+ $result[$slug] = [
+ 'name' => $family['name'] ?? $slug,
+ 'label' => $slug,
+ 'valid_before_s' => $valid_before,
+ 'description' => $family['description'] ?? '',
+ 'description_i18n' => $family['description_i18n'] ?? NULL,
+ ];
}
\Drupal::cache()->set($cid, $result, time() + self::CACHE_BACKEND_DATA_SECONDS);
return new TalerBackendResult(TalerBackendErrorKind::OK, httpStatus: $r->httpStatus, data: $result);