Skip to content

fix(region): signed integer overflow in RegionCommonComputeSymbolTimeLoRa at SF11/SF12#1648

Open
Alexey-Lukin wants to merge 1 commit into
Lora-net:masterfrom
Alexey-Lukin:fix/region-symbol-time-sf11-sf12-overflow
Open

fix(region): signed integer overflow in RegionCommonComputeSymbolTimeLoRa at SF11/SF12#1648
Alexey-Lukin wants to merge 1 commit into
Lora-net:masterfrom
Alexey-Lukin:fix/region-symbol-time-sf11-sf12-overflow

Conversation

@Alexey-Lukin

Copy link
Copy Markdown

Problem

RegionCommonComputeSymbolTimeLoRa() computes:

return ( 1 << phyDr ) * 1000000 / bandwidthInHz;

The multiplication is evaluated in (signed) int arithmetic. For phyDr >= 11 the intermediate product exceeds INT32_MAX (SF11: 2048 * 1e6 = 2.048e9; SF12: 4096 * 1e6 = 4.096e9), which is undefined behavior in C.

On typical two's-complement targets the wrapped intermediate makes the returned symbol time garbage (instead of e.g. 32768 µs for SF12 / 125 kHz), corrupting the RX window timeout/offset computation in RegionCommonComputeRxWindowParameters(). With a different compiler or optimization level the behavior is not defined at all — the optimizer is allowed to assume signed overflow never happens.

Caught by UndefinedBehaviorSanitizer while host-testing the MAC (OTAA join at DR0 / EU868) against a stub radio:

RegionCommon.c: runtime error: signed integer overflow: 4096 * 1000000 cannot be represented in type 'int'
    #0 RegionCommonComputeSymbolTimeLoRa RegionCommon.c
    #1 RegionEU868ComputeRxWindowParameters RegionEU868.c
    #2 ScheduleTx LoRaMac.c
    #3 LoRaMacMlmeRequest LoRaMac.c

Fix

Force the computation into uint32_t:

return ( ( uint32_t )1 << phyDr ) * 1000000U / bandwidthInHz;

The maximum intermediate value (4096 * 1000000 = 4.096e9) fits in an unsigned 32-bit integer, and the function already returns uint32_t.

Affects every region file that reaches this helper with SF11/SF12 (EU868 RX2/DR0 join being the most common path).

…LoRa at SF11/SF12

( 1 << phyDr ) * 1000000 is evaluated in (signed) int arithmetic. For
phyDr >= 11 the intermediate product (2048e6 / 4096e6) exceeds INT32_MAX,
which is undefined behavior in C. On typical two's-complement targets the
wrapped value makes the returned symbol time garbage instead of e.g.
32768 us for SF12/125kHz, corrupting the RX window timeout/offset
computation downstream; with a different compiler/optimization level the
behavior is not defined at all.

Force the computation into uint32_t: the maximum intermediate value
(4096 * 1000000 = 4.096e9) fits in an unsigned 32-bit integer.

Found by UndefinedBehaviorSanitizer while host-testing the MAC against a
stub radio (join at DR0/EU868):

  RegionCommon.c: runtime error: signed integer overflow:
  4096 * 1000000 cannot be represented in type 'int'
    #0 RegionCommonComputeSymbolTimeLoRa
    Lora-net#1 RegionEU868ComputeRxWindowParameters
    Lora-net#2 ScheduleTx
Alexey-Lukin added a commit to Alexey-Lukin/silken_net that referenced this pull request Jul 5, 2026
…55 ARCH.34) + drift-фікси аудиту

3 read-only аудитори (повні секції, verify-код, git-verify) — вердикт усіх
шести: cement-trim у формі, archive неможливий (живі live-gated residual).
Знайдений і закритий дрейф:

- ARCH.55 migrate-first: EVM-scoping (`blockchain_network: "evm"` з
  f0263f1) жив ЛИШЕ в git — канонізовано у 04_02 Side Effects (+
  BATCH_LIMIT-cap); 06_08 §3 досі числив re-arm 🟡-target'ом → окремий
  ✅-рядок; НОВА regression-спека «ignores stuck :sent on non-EVM»
  (стара проходила випадково — factory дефолтить evm); meta-реф §2.3→§3.
- ARCH.34: upstream-PR подано — Lora-net/LoRaMac-node#1648 (чекбокс ✅ +
  🔗-нагадування зняти форк при прийнятті); stale SHA 3b2c8b73 → тег-пін
  v2.6.2-silken.1 у 03_01 §12.5 і трекері (SHA дрейфить, тег = SSOT);
  volatile «специ 15/15» знято.
- INF.20-аудит: 06_01 §Firewall не знав allow-iap-ssh (канонічний шлях) —
  додано + allow-ssh перемаркований break-glass; 06_04 §4 чеклист без
  iap_admin_members — додано; deploy-production.yml ніс фантом
  KAMAL_MASTER_KEY у kamal-env (canopy давно чистий) — знято.
- INF.21: 06_02 §1.1 показував :latest без попередження — ⚠️-нотатка
  (static SDL = приклад, бойовий пін = tf-var docker_image).
- S2.2: verbose [x]-блок з volatile counts (36 панелей/22 правила) →
  тонкий рядок (spec-at-source = deploy/grafana + git).
- Гейт-кластери: FW.46-рядок — ARCH.34 machine-half повний, лишився ефір;
  CLAUDE.md §7 + firmware-скіл — lorawan_glue дім.

Full suite 7262/0; docs:check_refs + tracker:check зелені.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant