https://github.com/Lu4nScr1pt1ng updated https://github.com/llvm/llvm-project/pull/207793
>From 0e514541e3bb7ae4f20b67b79a2dbcf901cf0cf1 Mon Sep 17 00:00:00 2001 From: Lu4nScr1pt1ng <[email protected]> Date: Mon, 6 Jul 2026 14:48:08 -0300 Subject: [PATCH] [analyzer] Fix invalid HTML nesting in reports when tags close at end of line AddLineNumber inserted the row-closing </td></tr> with InsertTextBefore, which places it in front of previously inserted text at the same offset. When a variable with a variable_popup was the last token on a source line, the popup's closing </table></span> tags (and the arrow anchor </span> tags) were pushed outside the table row, producing malformed HTML that parsers and validators reject. Insert </td></tr> with InsertTextAfter instead, so tags closing at the end-of-line offset stay inside the row. To keep the message bubbles outside the code rows, add the line number table before processing the path pieces and insert the bubbles after the newline, between the current and the next row. Fixes #46089 --- clang/lib/Rewrite/HTMLRewrite.cpp | 2 +- .../StaticAnalyzer/Core/HTMLDiagnostics.cpp | 13 +++++---- .../html_diagnostics/variable-popups-eol.c | 27 +++++++++++++++++++ 3 files changed, 36 insertions(+), 6 deletions(-) create mode 100644 clang/test/Analysis/html_diagnostics/variable-popups-eol.c diff --git a/clang/lib/Rewrite/HTMLRewrite.cpp b/clang/lib/Rewrite/HTMLRewrite.cpp index 109cdf990543a..37fea7118c91f 100644 --- a/clang/lib/Rewrite/HTMLRewrite.cpp +++ b/clang/lib/Rewrite/HTMLRewrite.cpp @@ -247,7 +247,7 @@ static void AddLineNumber(RewriteBuffer &RB, unsigned LineNo, RB.InsertTextBefore(B, OS.str()); } else { RB.InsertTextBefore(B, OS.str()); - RB.InsertTextBefore(E, "</td></tr>"); + RB.InsertTextAfter(E, "</td></tr>"); } } diff --git a/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp index 77c1cceb60fe2..04829bffeecd9 100644 --- a/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp +++ b/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp @@ -786,6 +786,10 @@ static void HandlePopUpPieceEndTag(Rewriter &R, void HTMLDiagnostics::RewriteFile(Rewriter &R, const PathPieces &path, FileID FID) { + // Add line numbers first, so that tags inserted later at end-of-line + // offsets (e.g. pop-up closing tags) end up inside the row. + html::EscapeText(R, FID); + html::AddLineNumbers(R, FID); // Process the path. // Maintain the counts of extra note pieces separately. @@ -877,10 +881,6 @@ void HTMLDiagnostics::RewriteFile(Rewriter &R, const PathPieces &path, // Add the <table> start tag of pop-up pieces based on the stored ranges. HandlePopUpPieceStartTag(R, PopUpRanges); - // Add line numbers, header, footer, etc. - html::EscapeText(R, FID); - html::AddLineNumbers(R, FID); - addArrowSVGs(R, FID, ArrowIndices); // If we have a preprocessor, relex the file and syntax highlight. @@ -1096,8 +1096,11 @@ void HTMLDiagnostics::HandlePiece(Rewriter &R, FileID BugFileID, os << "</div></td></tr>"; - // Insert the new html. + // Insert the new html after the newline, so that the bubble's row lands + // between the current line's row and the next line's row. unsigned DisplayPos = LineEnd - FileStart; + if (LineEnd != FileEnd) + ++DisplayPos; SourceLocation Loc = SM.getLocForStartOfFile(LPosInfo.first).getLocWithOffset(DisplayPos); diff --git a/clang/test/Analysis/html_diagnostics/variable-popups-eol.c b/clang/test/Analysis/html_diagnostics/variable-popups-eol.c new file mode 100644 index 0000000000000..ae85534c06e9b --- /dev/null +++ b/clang/test/Analysis/html_diagnostics/variable-popups-eol.c @@ -0,0 +1,27 @@ +// RUN: rm -fR %t +// RUN: mkdir %t +// RUN: %clang_analyze_cc1 -analyzer-checker=core \ +// RUN: -analyzer-output=html -o %t -verify %s +// RUN: cat %t/report-*.html | FileCheck %s + +void bar(int); + +void foo(void) { + int a; + int b = 1; + if (b + && 1) + bar(a); // expected-warning{{1st function call argument is an uninitialized value}} +} + +// The variable 'b' is the last token on its line, so the popup's closing +// tags and the row's closing </td></tr> are inserted at the same offset. +// The popup table and the closing </span> must stay inside the row. +// CHECK: <span class='variable'>b +// CHECK-SAME: <table class='variable_popup'><tbody> +// CHECK-SAME: <tr><td valign='top'> +// CHECK-SAME: <div class='PathIndex PathIndexPopUp'>1.1</div> +// CHECK-SAME: </td><td>'b' is 1</td></tr> +// CHECK-SAME: </tbody></table> +// CHECK-SAME: </span> +// CHECK-SAME: </td></tr> _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
