diff mrjunejune/test/latex_renderer_test.c @ 244:b8aa08503378

[tools] Add sandboxed online LaTeX editor Co-authored-by: Copilot <[email protected]>
author MrJuneJune <me@mrjunejune.com>
date Mon, 03 Aug 2026 16:56:25 -0700
parents
children 70f2a3dafc1c
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrjunejune/test/latex_renderer_test.c	Mon Aug 03 16:56:25 2026 -0700
@@ -0,0 +1,105 @@
+#include "mrjunejune/latex_renderer.h"
+
+#include <assert.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+static size_t latex_workspace_count(void)
+{
+  DIR *directory = opendir("/tmp");
+  assert(directory);
+  size_t count = 0;
+  struct dirent *entry;
+  while ((entry = readdir(directory)) != NULL)
+  {
+    if (strncmp(entry->d_name, "mrjunejune-latex-", 19) == 0)
+      count++;
+  }
+  closedir(directory);
+  return count;
+}
+
+int main(void)
+{
+  size_t initial_workspaces = latex_workspace_count();
+
+  const char *valid =
+      "\\documentclass{article}\n"
+      "\\begin{document}\n"
+      "Hello from the sandbox. $x^2 + y^2 = z^2$\n"
+      "\\end{document}\n";
+  Latex_Render_Result result = Latex_Render(
+      (const uint8_t *)valid,
+      strlen(valid));
+  if (result.status != LATEX_RENDER_OK)
+    fprintf(stderr, "%s\n", result.diagnostics ? result.diagnostics : "unknown error");
+  assert(result.status == LATEX_RENDER_OK);
+  assert(result.pdf_size > 1000);
+  assert(memcmp(result.pdf_data, "%PDF-", 5) == 0);
+  Latex_Render_Result_Destroy(&result);
+
+  const char *invalid =
+      "\\documentclass{article}\n"
+      "\\begin{document}\n"
+      "\\notarealcommand\n"
+      "\\end{document}\n";
+  result = Latex_Render((const uint8_t *)invalid, strlen(invalid));
+  assert(result.status == LATEX_RENDER_COMPILE_ERROR);
+  assert(result.diagnostics);
+  assert(strstr(result.diagnostics, "Undefined control sequence"));
+  Latex_Render_Result_Destroy(&result);
+
+  const char *host_read =
+      "\\documentclass{article}\n"
+      "\\begin{document}\n"
+      "\\input{/etc/passwd}\n"
+      "\\end{document}\n";
+  result = Latex_Render((const uint8_t *)host_read, strlen(host_read));
+  assert(result.status == LATEX_RENDER_COMPILE_ERROR);
+  assert(result.diagnostics);
+  assert(!strstr(result.diagnostics, "root:x:"));
+  Latex_Render_Result_Destroy(&result);
+
+  char shell_path[128];
+  snprintf(
+      shell_path,
+      sizeof(shell_path),
+      "/tmp/mrjunejune-latex-shell-%ld",
+      (long)getpid());
+  char shell_escape[512];
+  snprintf(
+      shell_escape,
+      sizeof(shell_escape),
+      "\\documentclass{article}\n"
+      "\\begin{document}\n"
+      "\\immediate\\write18{touch %s}\n"
+      "Shell escape must stay disabled.\n"
+      "\\end{document}\n",
+      shell_path);
+  result = Latex_Render(
+      (const uint8_t *)shell_escape,
+      strlen(shell_escape));
+  assert(result.status == LATEX_RENDER_OK);
+  assert(access(shell_path, F_OK) != 0);
+  Latex_Render_Result_Destroy(&result);
+
+  uint8_t oversized[LATEX_SOURCE_MAX_BYTES + 1] = {0};
+  memset(oversized, 'x', sizeof(oversized));
+  result = Latex_Render(oversized, sizeof(oversized));
+  assert(result.status == LATEX_RENDER_INVALID_INPUT);
+  Latex_Render_Result_Destroy(&result);
+
+  const char *infinite =
+      "\\documentclass{article}\n"
+      "\\begin{document}\n"
+      "\\loop\\iftrue\\repeat\n"
+      "\\end{document}\n";
+  result = Latex_Render((const uint8_t *)infinite, strlen(infinite));
+  assert(result.status == LATEX_RENDER_TIMEOUT);
+  Latex_Render_Result_Destroy(&result);
+
+  assert(latex_workspace_count() == initial_workspaces);
+  return 0;
+}