fix(doclinks): never qsort an empty rst token vector

doclink_rst.c sorted d.toks unconditionally; the vector stays NULL until
the first token, and qsort's base is declared nonnull even for zero
elements. GCC UBSan on Linux amd64 reported it in rst_section_text_cut and
diagrams_rst ("null pointer passed as argument 1, which is declared to
never be null", doclink_rst.c:1767) -- the same class as the k8s pass fix.
Sort only when there are at least two tokens, as the file already does for
its section titles.

Proof: doc_links_rst on Linux amd64 (GCC, ASan+UBSan) reports the
violation without the change and none with it; doc_links_rst + diagrams on
macOS: 27 passed.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
This commit is contained in:
Martin Vogel committed 2026-10-13 18:33:40 +02:00
1 parent bb636d1ff7
commit 94d940ff24
1 file changed
+5 -1
+5 -1
View File
@@ -1764,7 +1764,11 @@ void cbm_doclink_rst_scan_file(CBMExtractCtx *ctx) {
ctx->result->doc_links.failed = true;
return;
}
qsort(d.toks, (size_t)d.ntoks, sizeof(*d.toks), rst_tok_cmp);
/* d.toks stays NULL until the first token: qsort's base is nonnull even
* for zero elements (glibc attribute; UBSan on Linux amd64, 2026-10-13). */
if (d.ntoks > 1) {
qsort(d.toks, (size_t)d.ntoks, sizeof(*d.toks), rst_tok_cmp);
}
for (int i = 0; i < d.ntoks; i++) {
const rst_tok_t *t = &d.toks[i];
const rst_title_t *sec = rst_section_of(&d, t->line);