From 119fed663252b3d148b00c0172d79828a7c13663 Mon Sep 17 00:00:00 2001 From: AntoineBastide47 <148970403+AntoineBastide47@users.noreply.github.com> Date: Sun, 7 Jun 2026 14:13:12 +0200 Subject: [PATCH 1/2] feat: add the empirical analysis results --- doc/.gitignore | 1 + doc/abs.tex | 6 + doc/eval.tex | 399 +++++++++++++++++++++++++++++----- doc/fig/appendix3_nesting.pdf | Bin 0 -> 26186 bytes doc/intro.tex | 15 +- doc/main.tex | 4 +- doc/thesis.bib | 13 ++ 7 files changed, 378 insertions(+), 60 deletions(-) create mode 100644 doc/fig/appendix3_nesting.pdf create mode 100644 doc/thesis.bib diff --git a/doc/.gitignore b/doc/.gitignore index ac4973b..b500c08 100644 --- a/doc/.gitignore +++ b/doc/.gitignore @@ -7,3 +7,4 @@ *.toc *.out *.pdf +!fig/appendix3_nesting.pdf \ No newline at end of file diff --git a/doc/abs.tex b/doc/abs.tex index 6bb8ea6..1eb1eb9 100644 --- a/doc/abs.tex +++ b/doc/abs.tex @@ -21,6 +21,12 @@ language syntaxes such as URIs, HTML, and JavaScript, exploring the benefits, costs, and compatibility issues in adopting the proposed matchertext discipline. +An empirical analysis of roughly 470~million string literals +drawn from thousands of production repositories +finds that real-world code is already overwhelmingly compliant +with this discipline, +and that adopting it could eliminate +around 95\% of the backslash escapes in string literals. We also present MinML, an experimental markup syntax designed around matchertext, as a concise but general alternative syntax for writing HTML or XML. diff --git a/doc/eval.tex b/doc/eval.tex index 1f71048..9ae7be6 100644 --- a/doc/eval.tex +++ b/doc/eval.tex @@ -1,25 +1,351 @@ \section{Evaluation} \label{sec:eval} -This section is a placeholder at present, -pending more implementation and evaluation experience to report. +To begin grounding the matchertext discipline in evidence +rather than argument, +we summarize an initial empirical evaluation of matchertext +on a large corpus of real-world code, +carried out as a large-scale measurement study~\cite{bastide26matchertext}. +The study treats every string literal and comment in the corpus +as a candidate embedded string, +and measures how close existing code already is +to the embedded-language side of matchertext compliance +(\cref{sec:host}), +and how much character escaping +adopting the discipline would remove. +Following the questions we raise above in \cref{sec:intro}, +it addresses four that can be measured directly from source code: +how matchertext-compliant existing code already is, +and whether violations concentrate in string literals or comments +(\cref{sec:eval:compliance}); +which embedded-language categories carry the violations +(\cref{sec:eval:where}); +how much of the escaping burden adopting matchertext would remove +(\cref{sec:eval:reduction}); +and how common nested, multi-level embedding is in practice +(\cref{sec:eval:nesting}). +Questions of security defects +and of the purposes of particular embeddings +are outside what the analysis measures, +and we return to them as open questions +in \cref{sec:eval:open}. -Some key questions we wish to evaluate include: + +\subsection{Methodology} +\label{sec:eval:methodology} + +The analysis extracts embedded text directly from each language's +own lexical structure rather than from ad-hoc pattern matching. +For C and C++ it uses the Clang lexer, +recognizing all string-literal forms (including the wide, UTF-8, +UTF-16, UTF-32, and raw variants) and both comment styles; +for the remaining languages it uses in-process tree-sitter grammars. +Both paths emit string-literal and comment samples +that feed the same metric computation. +Each candidate string is further classified by content -- +\eg as a URI, regular expression, HTML, SQL, or shell fragment -- +using deterministic structural detectors backed by +a trigram naive-Bayes model, +with an explicit \emph{Unknown} bucket for samples too short or ambiguous +to label safely. +The compliance and escaping metrics below +do not depend on this classification, +which affects only the per-category attribution of results. + +The corpus is drawn from GitHub +and is intended to represent mature, widely-deployed production code: +the main repositories of 79 organizations +behind operating-system kernels, databases, browsers, +language toolchains, and similar infrastructure. +It comprises 14,293 repositories and roughly 12.39~million source files +(on the order of 1.5~TiB of code), +yielding approximately 469.6~million string-literal samples +and 304.1~million comment (``documentation'') samples. +JavaScript alone contributes about 207~million string samples, +reflecting both its prevalence and its string-heavy style. + +The key metrics are as follows. +A sample is \emph{matchertext-compliant} +when its ASCII matchers match (\cref{sec:design}), +and the \emph{compliance rate} is the fraction of compliant samples; +a \emph{strict} rule treats a wrong-kind closer (\eg \verb|)| closing \verb|[|) +as a violation, while a \emph{relaxed} rule permits it. +A \emph{toothpick} is a single backslash character in a sample, +following the ``leaning toothpick syndrome'' of \cref{sec:bg}; +to estimate the escaping that matchertext would remove, +each compliant string literal is rewritten +as the equivalent escapeless C++ raw string literal \verb|R"(|$\dots$\verb|)"| +and the surviving backslashes are counted, +yielding a \emph{toothpick reduction}. +Finally, \emph{nesting depth} is the deepest matcher nesting a sample reaches. + + +\subsection{Compliance of existing code} +\label{sec:eval:compliance} + +Existing code is already highly matchertext-compliant +at the level of individual embedded fragments. +As \cref{tab:eval:compliance} shows, +98.57\% of string-literal samples +and 96.75\% of comment samples are compliant as written. +At the file level compliance is lower, 86.77\%, +because a single unmatched matcher anywhere in a file +makes the whole file non-compliant, +so per-sample-rare violations still touch a noticeable fraction of files. +The relaxed rule barely changes any of these figures +(file compliance rises only to 86.91\%, +comments to 96.78\%), +which means almost all violations are genuinely unmatched matchers +rather than correctly-paired-but-wrong-kind nesting. +Compliance is also high across every host language, +with string-literal compliance staying within a narrow band +from 95.20\% for the least-compliant language up to 99.92\%, +so no language in the corpus is broadly non-compliant. + +\begin{table}[t] +\begin{center} +\begin{footnotesize} +\begin{tabular}{lrrr} +\hline +Stream & Samples & Compliant & Compliant \\ + & & (strict) & (relaxed) \\ +\hline +String literals & 469.6\,M & 98.57\% & --- \\ +Documentation & 304.1\,M & 96.75\% & 96.78\% \\ +Files & 12.39\,M & 86.77\% & 86.91\% \\ +\hline +\end{tabular} +\end{footnotesize} +\end{center} +\caption{Matchertext compliance rate and sample size by stream, + under the strict and relaxed rules~\cite{bastide26matchertext}.} +\label{tab:eval:compliance} +\end{table} + + +\subsection{Where violations concentrate} +\label{sec:eval:where} + +Violations are far from evenly spread across embedded-language categories. +As \cref{tab:eval:categories} shows, +regular expressions and shell fragments alone +account for the largest violation counts +(670,118 and 534,719 respectively), +despite each making up only about 1.6\% of samples; +relative to their sample counts they are +far more often non-compliant than prose or identifiers. +CSS is similarly disproportionate, +contributing 98,186 violations from only 275,165 samples. +By contrast, identifier-like tokens and URLs +are essentially violation-free. +The pattern is that unmatched matchers cluster +in exactly the categories whose syntax routinely uses brackets singly, +rather than in the bulk categories +(plain prose, identifiers, file paths) +that dominate the sample count. + +This is precisely the pain point we anticipate +in \cref{sec:embed:c}: +printing and parsing code that emits or matches +lone, unmatched matchers within string literals -- +\eg \verb|print("[")| or \verb|case "]"| -- +is where the matchertext discipline bites. +Resolving the data by host language separates two effects. +The first is the per-sample violation \emph{rate}: +the bracket-single-use categories are most violation-prone +wherever they appear, and most acutely in JavaScript, +where regular expressions average 0.70 violations per sample, +shell fragments 0.41, and CSS 0.38. +The second is absolute \emph{contribution}, which is partly volume-driven: +in C++ and Java the single largest source of violations +is ordinary prose (46.3\% and 74.9\% of each language's violations), +not because prose is error-prone -- +its rate is only about 0.02 -- +but because prose strings are so numerous. +The category leading a host's violations thus differs by host, +but the categories intrinsically most likely to violate +are consistent across hosts. + +\begin{table}[t] +\begin{center} +\begin{footnotesize} +\begin{tabular}{lrrr} +\hline +Category & Share & Violations & Toothpicks \\ +\hline +PlainText & 40.6\% & 557,736 & 8,380,105 \\ +IdentifierLike & 31.1\% & 0 & 20,585 \\ +FilePath & 11.2\% & 12,932 & 455,055 \\ +FormatString & 5.8\% & 204,505 & 3,119,607 \\ +HTML & 1.8\% & 81,491 & 203,111 \\ +Regex & 1.6\% & 670,118 & 3,065,895 \\ +Shell & 1.6\% & 534,719 & 424,046 \\ +HexData & 1.4\% & 0 & 1,835 \\ +URL & 1.3\% & 983 & 3 \\ +\hline +\end{tabular} +\end{footnotesize} +\end{center} +\caption{Largest embedded-string categories by share of string samples, + with their accumulated violations and toothpicks; + categories below 1\% of samples are omitted~\cite{bastide26matchertext}.} +\label{tab:eval:categories} +\end{table} + + +\subsection{Escape reduction} +\label{sec:eval:reduction} + +The central benefit of matchertext is the escaping it removes. +Rewriting each compliant string literal +as an equivalent C++ raw string literal +eliminates 94.78\% of all toothpicks in the corpus, +cutting the string-literal toothpick total +from about 178.1~million to about 9.30~million. +As a concrete case, +the compliant C++ regular-expression literal +\verb|"\\b,\"axis\":(\\d+)\\b"| +carries eight toothpicks; +rewritten verbatim as the matchertext literal +\verb|M"(\b,"axis":(\d+)\b)"|, +the four quote-escapes vanish +and only the three genuine backslash escapes remain -- +a 62.5\% reduction in that one literal. + +The reduction is large but content-dependent. +Across the 79 organizations it ranges +from 23.6\% to 100\%, +but once a handful of low outliers are set aside +the bulk of organizations fall in an 85--100\% band. +As \cref{tab:eval:hostlang} shows, it also varies by host language: +mainstream C-family and JVM languages +see almost all of their compliant-literal toothpicks eliminated +(Java 99.93\%, JavaScript 99.82\%, Go 99.66\%), +while a few reduce much less, +most strikingly OCaml (19.86\%) and Python (42.89\%). + +A notable finding is that compliance and escape relief +are largely \emph{independent}, +turning on where a language's escaping actually lives. +Python is the clearest case: +its string literals are 99.54\% compliant, +among the highest in the corpus, +yet rewriting them removes only 42.89\% of their toothpicks, +among the lowest. +The reason is that most of Python's backslashes +sit in escaped binary-like strings +that are themselves non-compliant, +so the conversion never reaches them; +in JavaScript, by contrast, +almost all backslashes sit in compliant binary data +that the conversion does relieve. +A language can therefore satisfy the matchertext rule almost everywhere +and still gain little from raw-string rewriting: +the cost of becoming compliant +and the benefit of doing so are distinct quantities. + +\begin{table*}[t] +\begin{center} +\begin{footnotesize} +\begin{tabular}{lrrrrr} +\hline +Host language & Orgs & String samples & Compliance & Reduction & Max depth \\ +\hline +JavaScript & 77 & 206.8\,M & 98.52\% & 99.82\% & 11,777 \\ +Java & 49 & 66.9\,M & 97.24\% & 99.93\% & 50 \\ +Python & 72 & 34.0\,M & 99.54\% & 42.89\% & 8,394 \\ +Go & 43 & 30.9\,M & 99.20\% & 99.66\% & 652 \\ +C++ & 61 & 27.2\,M & 97.67\% & 93.45\% & 41,066 \\ +TypeScript & 62 & 20.0\,M & 99.75\% & 98.66\% & 333 \\ +C & 70 & 18.6\,M & 99.00\% & 91.55\% & 305 \\ +C\# & 37 & 18.3\,M & 98.76\% & 99.01\% & 3,757 \\ +Rust & 49 & 7.1\,M & 99.20\% & 98.44\% & 148 \\ +OCaml & 18 & 399\,k & 96.65\% & 19.86\% & 87 \\ +\hline +\end{tabular} +\end{footnotesize} +\end{center} +\caption{Per-host-language statistics for selected languages: + contributing organizations, string-sample count, + string-literal compliance rate, toothpick reduction, + and the deepest raw matcher nesting observed in any single sample. + OCaml is shown as the lowest-reduction language in the corpus~\cite{bastide26matchertext}.} +\label{tab:eval:hostlang} +\end{table*} + + +\subsection{Nested embedding} +\label{sec:eval:nesting} + +Most embedding is shallow. +The overwhelming majority of samples +reach a matcher nesting depth of only one, +and depth falls off sharply beyond that: +the average per-sample maximum depth +is only 0.102 for string literals +and 0.275 for comments. +Deep nesting does occur in a heavy tail -- +the single deepest string sample reaches a raw depth of 41,066, +in C++ (though that literal's deepest \emph{matched} nesting is only 500), +followed by maxima in JavaScript (11,777), Python (8,394), +and C\# (3,757) -- +but such cases are vanishingly rare. +Comments nest more on average than string literals, +consistent with comments containing structured examples and prose, +whereas string literals more often hold a single flat fragment. +\Cref{fig:eval:nesting} plots the full depth distribution +for both streams on log--log axes, +showing the sharp fall-off after depth one +and the long, sparse tail. + +\begin{figure}[t] +\begin{center} +\includegraphics[width=\columnwidth]{fig/appendix3_nesting.pdf} +\end{center} +\caption{Number of samples reaching each maximum raw nesting depth, + for string literals and comments + (log--log scale; only non-zero counts plotted)~\cite{bastide26matchertext}.} +\label{fig:eval:nesting} +\end{figure} + + +\subsection{Discussion and open questions} +\label{sec:eval:open} + +Taken together, these results suggest that the adoption cost +we anticipate above is small in practice +while the benefit is large. +Real code is already overwhelmingly valid matchertext +at the fragment level -- +better than 98\% of string literals and better than 97\% of comments +need no change at all -- +so for most code the transition would touch +only a small minority of fragments. +At the same time, rewriting the compliant majority as raw literals +removes nearly all of their escaping, +the corpus-wide 94.78\% reduction +being the empirical form of the relief from leaning toothpick syndrome +that matchertext aims to deliver. +The violations that remain fall exactly where \cref{sec:embed} predicts: +in regular expressions, shell fragments, format strings, and CSS, +whose syntax legitimately uses brackets singly, +and the near-identical strict and relaxed rates confirm +that the difficulty is genuinely unmatched matchers -- +addressable by the targeted lone-matcher escapes +of \cref{tab:unmatched-matchers} +rather than any change to nesting discipline. + +This evaluation is nonetheless only a first step. +It measures embedded-language compliance and escaping, +but several of the questions we raise in \cref{sec:intro} +remain open for future work: \begin{itemize} -\item What are the most common kinds of embeddings - that appear in large repositories of real source code, - in what host and embedded language combinations, - and for what purposes? -\item How common and what kinds of needs are there for - multiple levels of embedding in practice? -\item For a set of popular (big or little) languages, - how common are natural violations of matchertext discipline? - Of what kinds are most common (e.g., in string constants, comments)? - How painful would it be to fix these violations in typical code? -\item How common and painful are needs to escape embedded strings - when manually embedding into surrounding language strings? - For example, how commonly do actual URIs embedded into - actual program code need or use manual escaping? +\item For what \emph{purposes} are particular host and embedded + language combinations used in practice, + beyond the kinds of embedded content the corpus reveals? +\item How does matchertext affect the usability to users or developers + of common constructs in common embedding use-cases, + such as synthesizing or editing HTTP or SQL queries? \item How common have security bugs been related to inadequate or incorrect escape armoring when embedding untrusted content automatically? @@ -32,38 +358,7 @@ \section{Evaluation} but perhaps in other combinations of languages and/or resulting in other symptoms? \end{itemize} - - -\xxx{Prevalence of embedding versus unmatched matchers: - -The key advantage of matchertext is to simplify embedding, -but it has the cost of making it more cumbersome -to express unmatched matchers. -Is this a worthwhile tradeoff? - -\textbf{Experiment:} -For each of several popular programming languages, -(a) find a large repository of source code in that language -(\eg an open source software distribution); -(b) find a mature scanner/parser for that language; -(c) write a heuristic recognizer for a variety -of commonly-embedded strings in other ``big'' or ``little'' language syntaxes -(\eg regexes, URIs, IP addresses, JavaScript, $dots$); -(d) count the number of times that cross-language embeddings -appear in some form, -and the number of times that unmatched matchers appear. -Record and provide statistics on the contexts in which embeddings -and unmatched matchers appear -(\eg in function calls, if statements, case statements, comments, $dots$). - -Priority languages to evaluate include: -HTML (especially detecting embedded JavaScript); -JavaScript/TypeScript (especially with embedded HTML); -C, C++, Java, Go, Swift, Perl, Raku, PHP. - -It would probably be worth trying to -make the heuristic embedded string recognizer portable across languages -or find an existing one that is in some way. - -} - +The corpus and analyzer used here~\cite{bastide26matchertext} +provide a concrete basis for pursuing these questions, +and for extending the measurement +beyond the infrastructure-heavy code studied so far. \ No newline at end of file diff --git a/doc/fig/appendix3_nesting.pdf b/doc/fig/appendix3_nesting.pdf new file mode 100644 index 0000000000000000000000000000000000000000..4031abceff3c66d9ff25d930254ddc4fa3916211 GIT binary patch literal 26186 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 sE(TqKv0Xz#kOE{Zs-x6D1Y;B+ Date: Mon, 13 Jul 2026 14:43:07 +0200 Subject: [PATCH 2/2] feat: add embedding purposes subsection and consolidate open questions --- doc/eval.tex | 90 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 70 insertions(+), 20 deletions(-) diff --git a/doc/eval.tex b/doc/eval.tex index 9ae7be6..58e6869 100644 --- a/doc/eval.tex +++ b/doc/eval.tex @@ -24,11 +24,12 @@ \section{Evaluation} (\cref{sec:eval:reduction}); and how common nested, multi-level embedding is in practice (\cref{sec:eval:nesting}). -Questions of security defects -and of the purposes of particular embeddings -are outside what the analysis measures, -and we return to them as open questions -in \cref{sec:eval:open}. +The content classification additionally yields a partial view +of what these embeddings are used for (\cref{sec:eval:purposes}), +while the purpose behind each embedding, +together with questions of security defects, +lies outside what the analysis measures +and is taken up as open questions in \cref{sec:eval:open}. \subsection{Methodology} @@ -309,6 +310,63 @@ \subsection{Nested embedding} \end{figure} +\subsection{What embeddings are used for} +\label{sec:eval:purposes} + +The content classifier that attributes violations and toothpicks above +also gives a partial answer to a question we would otherwise leave open: +what these embeddings are actually \emph{for}. +The classifier labels the \emph{kind} of content in each string, +which is a proxy for its purpose; +it tells us that a fragment is an SQL query or a regular expression, +but not the developer's intent in assembling it. + +At that granularity the picture is clear. +Most string literals are not cross-language embeddings at all: +plain prose, identifier-like tokens, and file paths +together account for roughly 83\% of samples (\cref{tab:eval:categories}), +the labels, keys, and paths of ordinary programs. +The genuine embedded languages form the tail. +Beyond the format strings, regular expressions, shell fragments, +and HTML already visible in \cref{tab:eval:categories}, +the languages that motivate our injection discussion (\cref{sec:host:inject}) +appear only sparsely here: +SQL accounts for 1,003,602 samples (0.79\%), +CSS for 275,165 (0.22\%), +JSON for 244,319 (0.19\%), +and XML for 81,395 (0.06\%). +That these query and web-facing languages are so thin a slice +is itself informative. +The corpus is deliberately infrastructure-heavy +(kernels, databases, browsers, and toolchains, \cref{sec:eval:methodology}), +so the SQL-in-application-code and HTML-templating combinations +that dominate web software are under-represented, +and these figures should be read as a lower bound +on how common such combinations are in software at large. + +The data also speaks, more coarsely, to which host embeds what. +As \cref{sec:eval:where} shows, +the category a host most engages with is legible +from where its violations and escaping concentrate: +regular expressions and embedded binary data in JavaScript, +escaped binary-like blobs and URL-bearing strings in Python, +and ordinary prose in C++ and Java. +The intrinsically bracket-heavy mini-languages, regular expressions, +shell, and CSS, are the ones that recur as embeddings across hosts, +whereas the bulk categories differ between hosts mainly in volume. + +Two caveats bound these readings. +The classification is content-based and best-effort, +so the finer categories, especially heuristic ones +such as the pseudo-binary and pseudo-URL buckets, +are approximate rather than exact (\cref{sec:eval:methodology}). +And content type is only a proxy: +it characterizes what is embedded and how often, +not the human purpose behind each embedding, +which the corpus cannot recover +and which we leave to the usability studies noted below. + + \subsection{Discussion and open questions} \label{sec:eval:open} @@ -337,26 +395,18 @@ \subsection{Discussion and open questions} This evaluation is nonetheless only a first step. It measures embedded-language compliance and escaping, -but several of the questions we raise in \cref{sec:intro} +but two questions we raise in \cref{sec:intro} remain open for future work: \begin{itemize} -\item For what \emph{purposes} are particular host and embedded - language combinations used in practice, - beyond the kinds of embedded content the corpus reveals? \item How does matchertext affect the usability to users or developers of common constructs in common embedding use-cases, such as synthesizing or editing HTTP or SQL queries? -\item How common have security bugs been related to - inadequate or incorrect escape armoring - when embedding untrusted content automatically? -\item What is the security-critical ``attack surface'' - (\eg code size and complexity) - of typical string sanitizing mechanisms - for embedding of untrusted content? -\item What are the syntactic ``horror stories'' of cross-language embedding, - akin to leaning toothpick syndrome, - but perhaps in other combinations of languages - and/or resulting in other symptoms? +\item How does matchertext affect the frequency of syntax-related, + and especially security-related, bugs in typical code? + The structural injection resistance of \cref{sec:host:inject} + bears directly on this, + but measuring its effect on real defect rates + is beyond what a static corpus analysis can capture. \end{itemize} The corpus and analyzer used here~\cite{bastide26matchertext} provide a concrete basis for pursuing these questions,