ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
mdl_sanitize.h File Reference

Neutralise untrusted names before they reach a filesystem or XML sink. More...

#include <stddef.h>
#include <stdint.h>
Include dependency graph for mdl_sanitize.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

bool mdl_sanitize_segment (const char *raw, char *out, size_t cap)
 Rewrite an untrusted path segment into a safe single filename.
bool mdl_path_contained (const char *parent, const char *candidate)
 True when candidate is lexically contained under parent.
bool mdl_path_join (const char *parent, const char *seg, char *out, size_t cap)
 Join one safe child segment under a parent directory path.
bool mdl_xml_escape (const char *src, char *out, size_t cap)
 XML-escape src into out, failing rather than truncating.

Detailed Description

Neutralise untrusted names before they reach a filesystem or XML sink.

Chapter and series names come from attacker-controlled HTML (the last path segment of a scraped URL, an anchor's text). Left raw they flow into two dangerous sinks: filesystem paths (a .. segment escapes the output tree) and generated XML (an unescaped </&/" in a page filename breaks the EPUB this tool feeds back to the on-device reader). This module holds the three pure predicates that close those holes, kept out of the CLI's translation unit so they are unit-testable both directions.

Definition in file mdl_sanitize.h.

Function Documentation

◆ mdl_path_contained()

bool mdl_path_contained ( const char * parent,
const char * candidate )

True when candidate is lexically contained under parent.

A prefix test that treats a directory boundary as significant, so /a/b contains /a/b and /a/b/c but not /a/bb. Both paths are expected to be already resolved (e.g. via realpath) so the comparison is purely lexical; trailing slashes on parent are ignored.

Parameters
[in]parentAbsolute, resolved parent directory, or NULL.
[in]candidateAbsolute, resolved candidate path, or NULL.
Returns
Whether candidate is parent itself or a descendant of it.
Return values
truecandidate equals parent or lies beneath it.
falseEither argument is NULL/empty, or candidate is outside.
Precondition
parent and candidate, when non-NULL, are NUL-terminated strings.
The caller resolved both paths before calling (no .. remains).
Postcondition
Neither argument is modified.
Note
Thread-safe: depends only on its arguments.
Since
0.1.0
Postcondition
Documented outputs and the return value describe the same outcome.

Definition at line 231 of file mdl_sanitize.c.

References strlen(), and strncmp().

◆ mdl_path_join()

bool mdl_path_join ( const char * parent,
const char * seg,
char * out,
size_t cap )

Join one safe child segment under a parent directory path.

The single join primitive every series_dir/chapter_dir join routes through, so a traversal name can never reach mkdir, an archiver, or an output path. It refuses – rather than composing – a seg that is not a single filesystem-safe segment: an empty string, . or .., or any name containing a / (which also rejects an absolute seg such as /etc). A result that would not fit out is likewise refused rather than truncated, since a silently-shortened path would name a different directory. seg is expected to already be the output of mdl_sanitize_segment (or a leaf composed from such a slug); this predicate is the defence-in-depth gate that makes an escape structurally impossible even if that upstream step regressed.

Parameters
[in]parentParent directory path (NUL-terminated), or NULL.
[in]segCandidate child segment (NUL-terminated), or NULL.
[out]outDestination buffer receiving parent/seg.
[in]capCapacity of out in bytes.
Returns
Whether out holds the joined parent/seg path.
Return values
trueout is parent + '/' + seg, NUL-terminated.
falseA NULL/zero argument, an unsafe seg, or a non-fitting result.
Precondition
out, when non-NULL, has room for at least cap bytes.
The caller treats false as a hard error (no partial path is used).
Postcondition
On false with cap > 0, out[0] is '\0' (no usable partial path).
On true, out contains exactly one / more than parent did.
Note
Thread-safe: writes only caller-provided storage.
See also
mdl_sanitize_segment Produces the safe seg this join expects.
mdl_path_contained Runtime realpath check callers pair with this.
Since
0.1.0

Definition at line 269 of file mdl_sanitize.c.

References internal_has_separator(), internal_is_dot_segment(), memcpy(), and strlen().

Referenced by internal_build_export_metadata(), internal_cache_paths(), internal_cover_current(), internal_download_page_image(), internal_init_site_identity(), internal_library_remove_child(), internal_library_visit(), internal_pack_combined_dir(), internal_prepare_artifact_path(), internal_remove_stale_page_variants(), internal_resolve_cache_path(), internal_resolve_descriptor_path(), internal_resolve_one_leaf(), internal_resolve_removal_target(), internal_verify_artifact_entry(), internal_verify_library_root(), mdl_app_run_verify(), mdl_join_dir_under(), mdl_pack_one_meta(), priv_mdl_app_ensure_series_cover(), priv_mdl_cache_publish_body(), and priv_mdl_cache_read_body().

◆ mdl_sanitize_segment()

bool mdl_sanitize_segment ( const char * raw,
char * out,
size_t cap )

Rewrite an untrusted path segment into a safe single filename.

Produces a non-empty NUL-terminated name in out that is always a single filesystem-safe segment: characters outside [A-Za-z0-9._-] (including /, NUL, and control bytes) become _, the traversal names . and .. and an empty result fall back to a generated name, a Windows reserved device name (CON, NUL, COM1..LPT9, ...) is prefixed with _, and any input longer than cap - 1 bytes is truncated. Because the result can contain no / and is never ./.., joining it under a parent directory cannot escape that directory.

Parameters
[in]rawUntrusted candidate name (NUL-terminated), or NULL.
[out]outDestination buffer for the sanitised name.
[in]capCapacity of out in bytes (must be >= 2 for a useful name).
Returns
Whether raw was already fully safe (copied verbatim).
Return values
trueout equals raw: no substitution, fallback, or truncation.
falseout was rewritten – the caller may log the change.
Precondition
out, when the call is useful, has room for at least cap bytes.
cap >= 2 so at least one character plus a NUL fits.
Postcondition
out is NUL-terminated and contains no /, .-only, or .. result.
out is non-empty whenever cap >= 2.
Note
Thread-safe: writes only caller-provided storage.
Since
0.1.0

Definition at line 213 of file mdl_sanitize.c.

References internal_copy_sanitised(), internal_is_dot_segment(), internal_is_reserved_base(), internal_prepend_underscore(), and s_fallback_name.

Referenced by internal_run_prepared(), and mdl_urlname_last_segment().

◆ mdl_xml_escape()

bool mdl_xml_escape ( const char * src,
char * out,
size_t cap )

XML-escape src into out, failing rather than truncating.

Replaces the five XML metacharacters (&, <, >, ", ') with their predefined entities and copies everything else verbatim. Applied to every untrusted filename interpolated into the OPF, nav document and per-page XHTML so a page named a"><script>.jpg cannot break the container's well-formedness. If the escaped result would not fit, the function fails instead of emitting a truncated (and possibly malformed) document.

Parameters
[in]srcSource string (NUL-terminated), or NULL.
[out]outDestination buffer for the escaped, NUL-terminated result.
[in]capCapacity of out in bytes.
Returns
Whether the fully escaped string fit in out.
Return values
trueout holds the complete escaped form of src.
falsesrc/out was NULL, cap was 0, or the result did not fit.
Precondition
out, when non-NULL, has room for at least cap bytes.
The caller treats false as a hard error (no partial output is used).
Postcondition
On false with cap > 0, out[0] is '\0'.
src is not modified.
Note
Thread-safe: writes only caller-provided storage.
Since
0.1.0

Definition at line 313 of file mdl_sanitize.c.

References internal_xml_entity(), memcpy(), and strlen().

Referenced by internal_epub_prepare_creators(), internal_epub_prepare_optional(), internal_epub_prepare_text(), internal_epub_write_page_xhtml(), and internal_escape_comicinfo().