Skip to content

Fix static analysis issues - #1

Open
stephenkingston wants to merge 1 commit into
masterfrom
headless/3212e6dd/create-a-new-branch-fix-static-analysis-
Open

Fix static analysis issues#1
stephenkingston wants to merge 1 commit into
masterfrom
headless/3212e6dd/create-a-new-branch-fix-static-analysis-

Conversation

@stephenkingston

Copy link
Copy Markdown
Owner

Summary

This PR fixes a set of static analysis issues identified across four source files. Each change is described below.


Core/Inc/main.h — ODR / multiple-definition violation

newCommandAvailable and motor[3] were defined (not just declared) in a header. Every translation unit that included main.h got its own copy, causing undefined behaviour (multiple definitions of the same external-linkage object). Changed both to extern declarations; the single authoritative definitions now live in main.c.


Core/Src/main.c

Globals definition — Added the definitions of newCommandAvailable and motor[3] in the USER CODE PV section to match the extern declarations now in the header.

programInit() called before HAL_Init()programInit() was placed in USER CODE BEGIN 1, which runs before HAL_Init() and peripheral initialisation. It sets up timer handles and function pointers that depend on the HAL being ready. Moved the call to USER CODE BEGIN 2, after MX_USB_DEVICE_Init().

microsecondDelay() optimised away — The empty for loop body was silently deleted by the compiler at -O2/-O3, making the pulse width zero. Replaced with 72 __NOP() intrinsics (~1 µs at 72 MHz) which the compiler cannot remove.

rampDownCount out-of-bounds index into cosine[]rampDownCount is a uint8_t passed directly as an index into cosine[NO_OF_RAMP_STEPS] (64 entries). In both the long-move and short-move branches the value was computed from abs(targetCount - currentCount) without clamping, so values >= 64 caused an out-of-bounds read. Added an explicit clamp to NO_OF_RAMP_STEPS - 1 after the cast.

getDurationOfUninterruptedMovement() — negative array index — When numOfSteps == 0 or 1, the expression (numOfSteps/2) - 1 evaluates to -1, producing an out-of-bounds array access. Added an early return for numOfSteps <= 0, a safe idx clamp for the else branch, and replaced the magic number 64 with the existing NO_OF_RAMP_STEPS macro.

performDataValidation() wrong motor pointer — The else if branch used motor->absolutePosition and motor->newAbsoluteTarget (the parameter name motor shadowed the global array and always pointed at motor[0]). Changed to motor[i].absolutePosition / motor[i].newAbsoluteTarget so all three motors are validated correctly.

max() shadows stdlib macro — The local function max() conflicts with the max() macro defined in some standard library headers, causing silent macro expansion or redefinition warnings. Renamed to maxIndex() and updated the single call site.


Core/Src/stm32f1xx_it.c — TIM4 inconsistent pulse condition

The TIM2 and TIM3 ISRs use currentCount < targetCount to decide whether to set pulseFlag. The TIM4 ISR used currentCount != targetCount, which would also fire when currentCount > targetCount (overshoot), generating a spurious extra pulse. Changed to < for consistency.


USB_DEVICE/App/usbd_cdc_if.c — USB receive buffer overrun

receivedData is declared as uint8_t receivedData[12]. The copy loop iterated up to *Len bytes without checking whether *Len exceeded 12, allowing a host to overwrite memory beyond the buffer. Added a bounds check: copyLen = min(*Len, sizeof(receivedData)) before the loop.


Build note

The arm-none-eabi-gcc toolchain is not present in the CI VM, so a full build could not be verified automatically. The changes are syntactically correct C and have been reviewed against the HAL headers present in the repository.

- main.h: Change bare definitions of newCommandAvailable and motor[] to
  extern declarations to fix ODR (multiple-definition) violations when
  the header is included by more than one translation unit.

- main.c: Add authoritative definitions of newCommandAvailable and
  motor[3] in the USER CODE PV section.

- main.c: Move programInit() call from USER CODE BEGIN 1 (before
  HAL_Init()) to USER CODE BEGIN 2 (after all peripheral inits) so
  HAL and peripherals are ready before application state is set up.

- main.c: Replace empty microsecondDelay() loop with 72 __NOP() calls
  so the delay is not eliminated by the optimiser at -O2/-O3.

- main.c: Clamp rampDownCount to [0, NO_OF_RAMP_STEPS-1] before
  passing it to ramp() to prevent out-of-bounds access into cosine[].

- main.c: Guard getDurationOfUninterruptedMovement() against zero or
  negative numOfSteps (negative array index), guard the else-branch
  index, and replace the magic number 64 with NO_OF_RAMP_STEPS.

- main.c: Fix performDataValidation() else-if branch using motor->
  (which pointed at motor[0] via the shadowed global) to motor[i].

- main.c: Rename max() to maxIndex() to avoid shadowing the stdlib
  max() macro; update the single call site accordingly.

- stm32f1xx_it.c: Fix TIM4 ISR pulse condition from != to < to match
  TIM2/TIM3 and prevent spurious pulses when currentCount overshoots.

- usbd_cdc_if.c: Add bounds check before copying USB receive data into
  receivedData[12] to prevent buffer overrun when *Len > 12.
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