fix: three crashes found while packaging - #54
Merged
Spacefreak18 merged 3 commits intoSep 4, 2026
Merged
Conversation
`monocoque --help` aborted with `free(): invalid pointer` on Debian forky -- found by installing the released debian-latest .deb on the distro it is built for. gdb put it in monocoquesettingsfree() called straight from main(). The early-exit paths (`--help`, `--version`, bad parameters) jump to cleanup_final before any field of Parameters or MonocoqueSettings is assigned, and cleanup_final calls monocoquesettingsfree() and freeparams(), which free every pointer in both. malloc leaves those pointing at whatever was in the heap block. It is undefined behaviour everywhere; forky's glibc is simply the first to check, which is why the same source looked healthy on Debian stable and both Fedoras. calloc in all three entry points -- monocoque.c, monocoque-cli.c (the `monocoque` binary) and monocoque-gui.c. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Only 2 of 24 configured sound devices came up -- "Could not initialize Sound Device" for the other 22 -- and no shaker fired, on a rig whose PipeWire graph looked perfect: monocoque streams connected into all six filter chains, every node running. sounddev_init() is declared int and fell off its end without returning, so new_sound_device() read whatever was left in the return register and treated that as the error code. The PulseAudio streams had already connected by then; the device objects were simply freed and never fed telemetry again, which is why the graph looked right and nothing shook. Undefined behaviour, so it varies by build: the same config drives shakers from a locally compiled monocoque and not from the packaged one. Now returns usb_generic_shaker_init()'s own result. Verified against a live Assetto Corsa session on real hardware: 26 devices initialised, no failures, shakers working. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
gmonocoque died before drawing a window, in libconfig: #0 config_setting_get_member () from libconfig.so.9 #1 config_setting_lookup () #2 populate_device_list () find_default_config() required sim, api and car to all be present on an entry and skipped the entry if any lookup failed, so it returned -1; populate_device_list passed that -1 straight to config_setting_get_elem, got NULL back, and config_setting_lookup dereferenced it. No real config has all three. conf/monocoque.config -- the example this project's own README points at -- sets sim and car and never mentions api, so this crashed for anyone following the documentation. It stayed hidden in the Flatpak build only until that manifest was given access to the real ~/.config/monocoque; against an empty config there was nothing to look up. A key that isn't there no longer disqualifies a match, a -1 falls back to the first entry (which is what a single-entry config means anyway), and both NULL paths now return with a message instead of dereferencing. Verified by rebuilding the Flatpak and launching gmonocoque against the real config that crashed it: the window opens and stays up. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Owner
|
i might remove some of the comments but this is good. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Split out of #53 at your request — these are bugs the packaging work exposed, not packaging changes. None of them are needed for that PR. Three commits, five files, no build-system or CI changes.
sounddev_initnever returnssounddev_init()is declaredintand its last statement was a bare call tousb_generic_shaker_init(...). Falling off the end of a non-void function is undefined behaviour, sonew_sound_device()read whatever happened to be in the return register and treated most initialised devices as failures. The PulseAudio streams had in fact connected — visible in qpwgraph — but the devices were freed and never fed telemetry, so nothing shook. Observed as 22 of 24 configured shakers reporting "Could not initialize Sound Device".One word:
return.--helpfrees uninitialised pointersmonocoque.candmonocoque-cli.cmallocbothParametersandMonocoqueSettings, then--help/--version/ bad parametersgoto cleanup_final, which is:Every pointer in both structs is freed before any of them was assigned, so
mallocleaves them pointing at whatever was in the heap block. Found by installing the releaseddebian-latest.deb on Debian forky, wheremonocoque --helpaborts withfree(): invalid pointer; gdb put it inmonocoquesettingsfree()called straight frommain(). It is undefined behaviour everywhere — forky's glibc is simply the first to check, which is why the same source looks healthy on Debian stable and both Fedoras.callocin all three entry points, includingmonocoque-gui.c, wherefreeparams()walks the same struct on its early-exit paths.gmonocoquesegfaults on launch for common configsThree related problems in
mgui/uiconfighelper.c, the first of which is a behaviour change worth your judgement:find_default_config()requiredsim,apiandcarto all be present,continue-ing past any entry missing one.conf/monocoque.config— the example the README points at — setssimandcarand never mentionsapi, so every entry was skipped and the function returned -1. This now treats a missing key as unconstrained rather than disqualifying (absent behaves as"default"). That's the interpretation the shipped example config implies, but if you intended the stricter reading I'll rework it.The other two are straightforward guards:
config_num < 0now falls back to entry 0 rather than passing -1 toconfig_setting_get_elem, andselectedconfig/config_devicesare NULL-checked, becauseconfig_setting_lookupdereferences its argument — which is where it actually died, inside libconfig, before the window was ever drawn.Verified: builds clean against current master, and
monocoque --helpruns underMALLOC_CHECK_=3. The original abort was reproduced on Debian forky from the released .deb.🤖 Generated with Claude Code