Validate data loaded from SQLite to prevent crashes on corrupted databases - #22679
Merged
Conversation
…_name` and update `SELECT_HOST_INFO` to exclude null keys/values
…andling of null database values
…ared statements for better error handling
Contributor
There was a problem hiding this comment.
1 issue found across 8 files
Confidence score: 3/5
- In
src/database/sqlite/sqlite_health.c,sql_alert_cleanup()stops checkingsqlite3_stepreturn codes, so failed cleanup queries can be reported as successful; that can hide real database health problems and mislead operators after merge — restore explicitsqlite3_steperror handling (and failure logging/propagation) before merging.
Architecture diagram
sequenceDiagram
participant Agent as Agent (Startup/Runtime)
participant SQLite as SQLite Database
participant Valid as Validation Helpers
participant CLI as CLI Commands
participant Cloud as Netdata Cloud
Agent->>SQLite: Read host_info table
SQLite-->>Agent: (key, value) row
alt Invalid row (NULL key/value)
Agent->>Agent: NEW: Skip row (ignore corrupted data)
else Valid row
Agent->>Agent: Process system info
end
Agent->>SQLite: Read chart type from context
SQLite-->>Agent: chart_type string (possibly NULL)
alt Missing chart type
Agent->>Agent: NEW: Default to RRDSET_TYPE_LINE
else Valid type
Agent->>Agent: Use provided chart type
end
Agent->>SQLite: Load context entries (rrdcontext_load_context_callback)
SQLite-->>Agent: VERSIONED_CONTEXT_DATA with hub.version
alt Version not set (0)
Agent->>Agent: NEW: Skip entry (avoid dangling pointers)
else Version set
Agent->>Agent: Process context normally
end
Agent->>SQLite: Read schema migration table names/indexes
SQLite-->>Agent: table_name (possibly NULL)
alt NULL table name
Agent->>Agent: NEW: Skip corrupted entry
else Valid name
Agent->>Agent: Apply schema upgrade
end
Agent->>SQLite: Read alert log entries for Cloud push
SQLite-->>Agent: chart, name columns (possibly NULL)
alt Missing chart or name
Agent->>Agent: NEW: strdupz("") for empty values
Agent->>Cloud: Send alert with empty fields
else Valid chart/name
Agent->>Cloud: Send alert normally
end
CLI->>SQLite: remove-stale-node: Read host entries
SQLite-->>CLI: host_id UUID blob
alt Invalid or truncated UUID
CLI->>CLI: NEW: Skip entry (continue loop)
else Valid UUID
CLI->>Agent: Process host removal
end
CLI->>SQLite: sqlite-alert-cleanup: Read host entries
SQLite-->>CLI: host_id, hostname columns
alt Invalid host_id (uuid_copy fails)
CLI->>CLI: NEW: Log "skipping host", continue
CLI->>CLI: Loop to next row
else Valid host_id
CLI->>CLI: Process alert cleanup for host
end
Note over Agent,SQLite: All reads now use safe validation helpers<br/>(sqlite3_column_uuid_copy, sqlite3_text_strdupz_empty,<br/>null checks) before dereferencing
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
…ts in SQLite loops
…dex operations into reusable helpers
|
stelfrag
marked this pull request as ready for review
June 12, 2026 08:18
Collaborator
Author
|
@cubic-dev-ai review PR |
Contributor
@stelfrag I have started the AI code review. It will take a few minutes to complete. |
Contributor
There was a problem hiding this comment.
No issues found across 8 files
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Architecture diagram
sequenceDiagram
participant Agent as Netdata Agent
participant SQLite as SQLite Database
participant FS as File System
participant Cloud as Netdata Cloud
Note over Agent,Cloud: READ FLOW: Corrupted SQLite rows handled safely
Agent->>SQLite: SELECT system_key, system_value FROM host_info
SQLite-->>Agent: Row with NULL key/value (corrupted)
alt Valid row (key AND value NOT NULL)
Agent->>Agent: rrdhost_system_info_set_by_name(key, value)
else NEW: NULL key or value
Agent->>Agent: Skip bad row → no crash
end
Agent->>SQLite: SELECT type FROM context_entry
SQLite-->>Agent: NULL type (corrupted)
alt Valid type
Agent->>Agent: rrdset_type_id(type)
else NEW: NULL type
Agent->>Agent: Return RRDSET_TYPE_LINE (default)
end
Agent->>SQLite: SELECT version, id, ... FROM context_data
SQLite-->>Agent: Row with version = 0 (unset)
alt version > 0
Agent->>Agent: rrdcontext_load_context_callback() — copy strings
else NEW: version == 0
Agent->>Agent: Skip row → no dangling pointer
end
Agent->>SQLite: SELECT chart, name, ... FROM alert_log
SQLite-->>Agent: Row with NULL chart or name
alt Valid chart/name
Agent->>Agent: strdupz(chart), strdupz(name)
else CHANGED: NULL chart or name
Agent->>Agent: sqlite3_text_strdupz_empty() → empty string
Agent->>Cloud: Send alert with empty chart/name
end
Note over Agent,SQLite: READ FLOW: CLI commands safe against corrupted host_id
Agent->>SQLite: SELECT host_id, hostname FROM host
SQLite-->>Agent: Row with invalid/truncated host_id
alt Valid UUID
Agent->>Agent: uuid_unparse_lower() → process host
else NEW: Invalid UUID
Agent->>Agent: Skip host → log warning, no crash
end
Note over Agent,SQLite: MIGRATION FLOW: Schema upgrades skip corrupted metadata
SQLite->>FS: Read sqlite_schema for table/index names
alt Valid name (non-NULL text)
Agent->>SQLite: ALTER TABLE/ANALYZE/DROP INDEX
else NEW: NULL name (corrupted catalog)
Agent->>Agent: Skip bad table/index → migration continues
end
thiagoftsm
approved these changes
Jun 15, 2026
thiagoftsm
left a comment
Contributor
There was a problem hiding this comment.
No issue found during runtime. LGTM!
Merged
Ferroin
pushed a commit
that referenced
this pull request
Jul 15, 2026
…bases (#22679) * Add null checks for `name` and `value` in `rrdhost_system_info_set_by_name` and update `SELECT_HOST_INFO` to exclude null keys/values * Add null check for `name` in `rrdset_type_id` to prevent undefined behavior * Replace `strdupz` logic with `sqlite3_text_strdupz_empty` for safer handling of null database values * Add UUID parsing safeguard to skip invalid rows in ephemeral host cleanup loop * Refactor alert cleanup to remove `sqlite3_exec` callback and use prepared statements for better error handling * Add null checks for `name` in SQLite migration loops to prevent undefined behavior * Add safeguard to skip SQLite insert callback for rows without version set * Add error handling for alert cleanup by logging non-SQLITE_DONE results in SQLite loops * Refactor SQLite migration logic to centralize repetitive table and index operations into reusable helpers (cherry picked from commit fbf1845)
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.



Summary
SQLite enforces schema constraints (
NOT NULL, types, lengths) only at write time. When reading a database damaged by storage failures or modified outside the agent, any column can return SQL NULL, an unexpected type, or a blob of any length.An audit of every
sqlite3_column_*read site found seven places that dereference such values unvalidated, crashing the agent — three of them during startup, turning one bad row into a permanent boot loop.All fixes route through validation helpers that already exist in the codebase.
Behavior for valid data is unchanged; malformed rows are skipped instead of crashing.
host_infotable crashed the agent on every startup. Bad rows are now ignored.line).remove-stale-nodeCLI command — a host entry with a missing or truncated host ID crashed the command; such entries are now skipped.sqlite-alert-cleanupCLI command — same problem; the lookup was also reworked so the host ID can be fully validated before use.Summary by cubic
Validate and sanitize SQLite reads to prevent crashes on corrupted or externally modified databases. Invalid rows are skipped or defaulted, fixing startup loops and runtime failures without changing behavior for valid data; also simplifies migration code for safer upgrades.
Bug Fixes
linewhen missing; fix startup crash.host_idUUIDs.host_id; log and continue.Refactors
sqlite3_execcallback in alert cleanup with prepared statements for clearer control flow and errors.Written for commit 6f61354. Summary will update on new commits.