The 9-byte auth_prefix buffer tripped -Wformat-truncation because auth is
64 bytes. Use %.8s in the Warning format instead, which truncates at print
time and drops the buffer. Logged output is unchanged: first 8 chars of the
hash plus "..." when longer.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
strncpy() into a fixed 9-byte buffer trips -Wstringop-truncation at -O2:
error: 'char* strncpy(char*, const char*, size_t)' output may be
truncated copying 8 bytes from a string of length 63
The truncation is deliberate (log only the first 8 chars of the auth
hash) and the copy was already safe, since auth_prefix is zero
initialised so the final byte stays NUL. snprintf() expresses the same
intent, always NUL-terminates, and does not warn.
Only reproducible in an optimised build; -O0 Debug trees never see it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Add instrumentation to trace which stream type and workload precede the
occasional runaway memory growth in nph-zms.
- zm_utils: add zm_get_rss_kb() reading resident set size from
/proc/self/statm
- zms: log a one-shot Debug summary of the decoded request (source, mode,
monitor/event, connkey, scale, buffer, ttl, rss) so a runaway process
can be tied to its stream parameters
- MonitorStream/EventStream: emit a periodic Debug RSS trace every 30s.
The EventStream trace includes frames-vector size and frame_count,
which scale with reloaded event length and will show whether the
in-process event reload path drives the growth
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The previous warning ("Unable to authenticate user from <referer>") gave
no way to distinguish the common cases without flipping on Debug:
- Stale auth hash on a long-lived <img src=nph-zms?...> whose TTL expired
- Missing/wrong user= or auth= in URL
- Disabled/deleted user
- REMOTE_ADDR mismatch when ZM_AUTH_HASH_IPS is enabled
Include user, auth-hash prefix, REQUEST_URI, XFF, and REMOTE_ADDR in
the message so the noise is diagnosable from the log alone.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
When a browser closes a streaming connection, fwrite to stdout raises
SIGPIPE. Without a handler the default action terminates the process
immediately, skipping exit_zm() and leaving the DB handle and log
unclosed.
Add zm_pipe_handler that sets zm_terminate so zms falls out of its
streaming loop and exits through the normal shutdown path. Clarify
the sendFrame comment to match.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add user= parameter to get_auth_relay() so zms can use the indexed
Username column instead of iterating all users to validate the hash
- Apply the same fix to Event.php getStreamSrc() and getThumbnailSrc()
- Tighten Monitor.php from isset() to !empty() for consistency
- In MonitorStream.js start(), check if the auth hash in the img src
matches the current auth_hash before resuming via CMD_PLAY. If stale,
fall through to rebuild the URL with fresh auth_relay. This prevents
long-running montage pages from spawning zms with expired credentials.
- Downgrade zms auth failure from Error to Warning
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
FFmpeg is an integral component of ZM. Promote the appropriate libraries to required dependencies.
This reduces the possible build configurations greatly and thus maintenance burden.
gmtime uses an internal static storage to which a pointer is given as return value.
Due to this it is not safe to call gmtime from multiple threads since the same static storage is used.
Use gmtime_r instead which allows to pass in a tm struct.
Fixes:
https://github.com/ZoneMinder/zoneminder/security/code-scanning/32
Remove calls to zmDBConnect from various places to avoid possible side-effects/double initialization.
The function should be called once from the main thread of the daemon.
Also split config loading into 2 steps: static and DB config loading. Load the static config before zmDBConnect is called so it has a chance to succeed.
With this commit a unified structure for includes is introduced.
The general rules:
* Only include what you need
* Include wherever possible in the cpp and forward-declare in the header
The includes are sorted in a local to global fashion. This means for the include order:
0. If cpp file: The corresponding h file and an empty line
1. Includes from the project sorted alphabetically
2. System/library includes sorted alphabetically
3. Conditional includes