Skip to content

Commit 2ae60e4

Browse files
Merge pull request #8681 from sagemathinc/fix-sagetex-clean-8680
frontend/latex: fix sagetex vs. clean issue
2 parents 2d22120 + 04b404c commit 2ae60e4

File tree

4 files changed

+42
-6
lines changed

4 files changed

+42
-6
lines changed

src/packages/frontend/frame-editors/latex-editor/actions.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ import { once } from "@cocalc/util/async-utils";
5050
import { ExecOutput } from "@cocalc/util/db-schema/projects";
5151
import {
5252
change_filename_extension,
53+
is_bad_latex_filename,
5354
path_split,
5455
separate_file_extension,
5556
sha1,
@@ -238,9 +239,10 @@ export class Actions extends BaseActions<LatexEditorState> {
238239

239240
private init_bad_filename(): void {
240241
// #3230 two or more spaces
242+
// Shell injection prevention: single quotes break bash string interpolation
241243
// note: if there are additional reasons why a filename is bad, add it to the
242244
// alert msg in run_build.
243-
this.bad_filename = /\s\s+/.test(this.path);
245+
this.bad_filename = is_bad_latex_filename(this.path);
244246
}
245247

246248
private init_ext_filename(): void {
@@ -878,7 +880,7 @@ export class Actions extends BaseActions<LatexEditorState> {
878880

879881
if (this.bad_filename) {
880882
const err = `ERROR: It is not possible to compile this LaTeX file with the name '${this.path}'.
881-
Please modify the filename, such that it does **not** contain two or more consecutive spaces.`;
883+
Please modify the filename, such that it does **not** contain two or more consecutive spaces or single quotes (').`;
882884
this.set_error(err);
883885
return;
884886
}

src/packages/frontend/frame-editors/latex-editor/sagetex.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
2+
* This file is part of CoCalc: Copyright © 2020-2025 Sagemath, Inc.
33
* License: MS-RSL – see LICENSE.md for details
44
*/
55

@@ -33,18 +33,26 @@ export async function sagetex_hash(
3333
const { base, directory } = parse_path(path); // base, directory, filename
3434
const s = sagetex_file(base);
3535
status(`sha1sum ${s}`);
36+
37+
// Check if file exists and compute hash only if it does; otherwise return unique value
3638
const output = await exec(
3739
{
3840
timeout: 10,
39-
command: "sha1sum",
40-
args: [s],
41+
command: `test -f '${s}' && sha1sum '${s}' || true`,
42+
bash: true,
4143
project_id: project_id,
4244
path: output_directory || directory,
43-
err_on_exit: true,
45+
err_on_exit: false,
4446
aggregate: time,
4547
},
4648
path,
4749
);
50+
51+
// If file doesn't exist, return unique timestamp-based value to ensure rebuild
52+
if (!output.stdout.trim()) {
53+
return `missing-${Date.now()}`;
54+
}
55+
4856
return output.stdout.split(" ")[0];
4957
}
5058

src/packages/util/misc.test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,24 @@ test("EDITOR_PREFIX", () => {
160160
expect(misc.EDITOR_PREFIX).toBe("editor-");
161161
});
162162

163+
describe("is_bad_latex_filename", () => {
164+
test("allows filenames without double spaces or quotes", () => {
165+
expect(misc.is_bad_latex_filename("paper.tex")).toBe(false);
166+
expect(misc.is_bad_latex_filename("my paper.tex")).toBe(false);
167+
expect(misc.is_bad_latex_filename("folder/subfolder/file.tex")).toBe(false);
168+
});
169+
170+
test("rejects filenames with double spaces", () => {
171+
expect(misc.is_bad_latex_filename("my paper.tex")).toBe(true);
172+
expect(misc.is_bad_latex_filename("folder/bad name/file.tex")).toBe(true);
173+
});
174+
175+
test("rejects filenames with single quotes", () => {
176+
expect(misc.is_bad_latex_filename("author's-notes.tex")).toBe(true);
177+
expect(misc.is_bad_latex_filename("folder/author's-notes.tex")).toBe(true);
178+
});
179+
});
180+
163181
describe("test code for displaying numbers as currency with 2 or sometimes 3 decimals of precision", () => {
164182
const { currency } = misc;
165183
it("displays 1.23", () => {

src/packages/util/misc.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,14 @@ export function change_filename_extension(
160160
return `${name}.${new_ext}`;
161161
}
162162

163+
// Check if a filename contains characters that are problematic for LaTeX compilation.
164+
// Returns true if the filename contains:
165+
// - Two or more consecutive spaces (breaks LaTeX processing, see #3230)
166+
// - Single quotes (breaks bash string interpolation in build commands)
167+
export function is_bad_latex_filename(path: string): boolean {
168+
return /\s\s+|'/.test(path);
169+
}
170+
163171
// Takes parts to a path and intelligently merges them on '/'.
164172
// Continuous non-'/' portions of each part will have at most
165173
// one '/' on either side.

0 commit comments

Comments
 (0)