summaryrefslogtreecommitdiff
path: root/src/th.h
diff options
context:
space:
mode:
authorcashmere <cashmere@autistici.org>2026-09-04 09:05:24 +0200
committercashmere <cashmere@autistici.org>2026-09-04 09:05:24 +0200
commit4f49b16079b27d7ce633619e4cddfdf2bffbc952 (patch)
treec296c1e7f3c3e2f6859c6d3a1b1b208779b89679 /src/th.h
downloadrelic-4f49b16079b27d7ce633619e4cddfdf2bffbc952.tar.gz
initial commitHEADmaster
Diffstat (limited to 'src/th.h')
-rw-r--r--src/th.h276
1 files changed, 276 insertions, 0 deletions
diff --git a/src/th.h b/src/th.h
new file mode 100644
index 0000000..1ef3566
--- /dev/null
+++ b/src/th.h
@@ -0,0 +1,276 @@
+/* This header file defines the external interface to the custom Scripting
+** Language (TH) interpreter. TH is very similar to Tcl but is not an
+** exact clone.
+**
+** TH1 was original developed to run SQLite tests on SymbianOS. This version
+** of TH1 was repurposed as a scripted language for Fossil, and was heavily
+** modified for that purpose, beginning in early 2008.
+**
+** More recently, TH1 has been enhanced to distinguish between regular text
+** and "tainted" text. "Tainted" text is text that might have originated
+** from an outside source and hence might not be trustworthy. To prevent
+** cross-site scripting (XSS) and SQL-injections and similar attacks,
+** tainted text should not be used for the following purposes:
+**
+** * executed as TH1 script or expression.
+** * output as HTML or Javascript
+** * used as part of an SQL query
+**
+** Tainted text can be converted into a safe form using commands like
+** "htmlize". And some commands ("query" and "expr") know how to use
+** potentially tainted variable values directly, and thus can bypass
+** the restrictions above.
+**
+** Whether a string is clean or tainted is determined by its length integer.
+** TH1 limits strings to be no more than 0x0fffffff bytes bytes in length
+** (about 268MB - more than sufficient for the purposes of Fossil). The top
+** bit of the length integer is the sign bit, of course. The next three bits
+** are reserved. One of those, the 0x10000000 bit, marks tainted strings.
+*/
+#define TH1_MX_STRLEN 0x0fffffff /* Maximum length of a TH1-C string */
+#define TH1_TAINT_BIT 0x10000000 /* The taint bit */
+#define TH1_SIGN 0x80000000
+
+/* Convert an integer into a string length. Negative values remain negative */
+#define TH1_LEN(X) ((TH1_SIGN|TH1_MX_STRLEN)&(X))
+
+/* Return true if the string is tainted */
+#define TH1_TAINTED(X) (((X)&TH1_TAINT_BIT)!=0)
+
+/* Remove taint from a string */
+#define TH1_RM_TAINT(X) ((X)&~TH1_TAINT_BIT)
+
+/* Add taint to a string */
+#define TH1_ADD_TAINT(X) ((X)|TH1_TAINT_BIT)
+
+/* If B is tainted, make A tainted too */
+#define TH1_XFER_TAINT(A,B) (A)|=(TH1_TAINT_BIT&(B))
+
+/* Check to see if a string is too big for TH1 */
+#define TH1_SIZECHECK(N) if((N)>TH1_MX_STRLEN){Th_OversizeString();}
+void Th_OversizeString(void);
+
+/*
+** Before creating an interpreter, the application must allocate and
+** populate an instance of the following structure. It must remain valid
+** for the lifetime of the interpreter.
+*/
+typedef struct Th_Vtab Th_Vtab;
+struct Th_Vtab {
+ void *(*xMalloc)(unsigned int);
+ void (*xFree)(void *);
+};
+
+/*
+** Opaque handle for interpeter.
+*/
+typedef struct Th_Interp Th_Interp;
+
+/*
+** Create and delete interpreters.
+*/
+Th_Interp * Th_CreateInterp(Th_Vtab *);
+void Th_DeleteInterp(Th_Interp *);
+
+/*
+** Report taint in the string zStr,nStr. That string represents "zTitle"
+** If non-zero is returned error out of the caller.
+*/
+int Th_ReportTaint(Th_Interp*,const char*,const char*zStr,int nStr);
+
+/*
+** Evaluate an TH program in the stack frame identified by parameter
+** iFrame, according to the following rules:
+**
+** * If iFrame is 0, this means the current frame.
+**
+** * If iFrame is negative, then the nth frame up the stack, where n is
+** the absolute value of iFrame. A value of -1 means the calling
+** procedure.
+**
+** * If iFrame is +ve, then the nth frame from the bottom of the stack.
+** An iFrame value of 1 means the toplevel (global) frame.
+*/
+int Th_Eval(Th_Interp *interp, int iFrame, const char *zProg, int nProg);
+
+/*
+** Evaluate a TH expression. The result is stored in the
+** interpreter result.
+*/
+int Th_Expr(Th_Interp *interp, const char *, int);
+
+/*
+** Access TH variables in the current stack frame. If the variable name
+** begins with "::", the lookup is in the top level (global) frame.
+*/
+int Th_ExistsVar(Th_Interp *, const char *, int);
+int Th_ExistsArrayVar(Th_Interp *, const char *, int);
+int Th_GetVar(Th_Interp *, const char *, int);
+int Th_SetVar(Th_Interp *, const char *, int, const char *, int);
+int Th_LinkVar(Th_Interp *, const char *, int, int, const char *, int);
+int Th_UnsetVar(Th_Interp *, const char *, int);
+
+typedef int (*Th_CommandProc)(Th_Interp *, void *, int, const char **, int *);
+
+/*
+** Register new commands.
+*/
+int Th_CreateCommand(
+ Th_Interp *interp,
+ const char *zName,
+ /* int (*xProc)(Th_Interp *, void *, int, const char **, int *), */
+ Th_CommandProc xProc,
+ void *pContext,
+ void (*xDel)(Th_Interp *, void *)
+);
+
+/*
+** Delete or rename commands.
+*/
+int Th_RenameCommand(Th_Interp *, const char *, int, const char *, int);
+
+/*
+** Push a new stack frame (local variable context) onto the interpreter
+** stack, call the function supplied as parameter xCall with the two
+** context arguments,
+**
+** xCall(interp, pContext1, pContext2)
+**
+** , then pop the frame off of the interpreter stack. The value returned
+** by the xCall() function is returned as the result of this function.
+**
+** This is intended for use by the implementation of commands such as
+** those created by [proc].
+*/
+int Th_InFrame(Th_Interp *interp,
+ int (*xCall)(Th_Interp *, void *pContext1, void *pContext2),
+ void *pContext1,
+ void *pContext2
+);
+
+/*
+** Valid return codes for xProc callbacks.
+*/
+#define TH_OK 0
+#define TH_ERROR 1
+#define TH_BREAK 2
+#define TH_RETURN 3
+#define TH_CONTINUE 4
+#define TH_RETURN2 5
+
+/*
+** Set and get the interpreter result.
+*/
+int Th_SetResult(Th_Interp *, const char *, int);
+const char *Th_GetResult(Th_Interp *, int *);
+char *Th_TakeResult(Th_Interp *, int *);
+
+/*
+** Set an error message as the interpreter result. This also
+** sets the global stack-trace variable $::th_stack_trace.
+*/
+int Th_ErrorMessage(Th_Interp *, const char *, const char *, int);
+
+/*
+** Access the memory management functions associated with the specified
+** interpreter.
+*/
+#if defined(TH_MEMDEBUG)
+void *Th_DbgMalloc(Th_Interp *, int);
+void Th_DbgFree(Th_Interp *, void *);
+#endif
+
+void *fossil_malloc_zero(size_t);
+void *fossil_realloc(void *, size_t);
+void fossil_free(void *);
+
+#define Th_SysMalloc(I,N) fossil_malloc_zero((N))
+#define Th_SysRealloc(I,P,N) fossil_realloc((P),(N))
+#define Th_SysFree(I,P) fossil_free((P))
+
+#if defined(TH_MEMDEBUG)
+# define Th_Malloc(I,N) Th_DbgMalloc((I),(N))
+# define Th_Free(I,P) Th_DbgFree((I),(P))
+#else
+# define Th_Malloc(I,N) Th_SysMalloc((I),(N))
+# define Th_Realloc(I,P,N) Th_SysRealloc((I),(P),(N))
+# define Th_Free(I,P) Th_SysFree((I),(P))
+#endif
+
+/*
+** Functions for handling TH lists.
+*/
+int Th_ListAppend(Th_Interp *, char **, int *, const char *, int);
+int Th_SplitList(Th_Interp *, const char *, int, char ***, int **, int *);
+
+int Th_StringAppend(Th_Interp *, char **, int *, const char *, int);
+
+/*
+** Functions for handling numbers and pointers.
+*/
+int Th_ToInt(Th_Interp *, const char *, int, int *);
+int Th_ToDouble(Th_Interp *, const char *, int, double *);
+int Th_SetResultInt(Th_Interp *, int);
+int Th_SetResultDouble(Th_Interp *, double);
+
+/*
+** Functions for handling command and variable introspection.
+*/
+int Th_ListAppendCommands(Th_Interp *, char **, int *);
+int Th_ListAppendVariables(Th_Interp *, char **, int *);
+int Th_ListAppendArray(Th_Interp *, const char *, int, char **, int *);
+
+/*
+** Drop in replacements for the corresponding standard library functions.
+*/
+int th_strlen(const char *);
+int th_isdigit(char);
+int th_isspace(char);
+int th_isalnum(char);
+int th_isalpha(char);
+int th_isspecial(char);
+int th_ishexdig(char);
+int th_isoctdig(char);
+int th_isbindig(char);
+char *th_strdup(Th_Interp *interp, const char *z, int n);
+
+/*
+** Interfaces to register the language extensions.
+*/
+int th_register_language(Th_Interp *interp); /* th_lang.c */
+int th_register_sqlite(Th_Interp *interp); /* th_sqlite.c */
+int th_register_vfs(Th_Interp *interp); /* th_vfs.c */
+int th_register_testvfs(Th_Interp *interp); /* th_testvfs.c */
+
+#ifdef FOSSIL_ENABLE_TCL
+/*
+** Interfaces to the full Tcl core library from "th_tcl.c".
+*/
+int th_register_tcl(Th_Interp *, void *);
+int unloadTcl(Th_Interp *, void *);
+int evaluateTclWithEvents(Th_Interp *,void *,const char *,int,int,int,int);
+#endif
+
+/*
+** General purpose hash table from th_lang.c.
+*/
+typedef struct Th_Hash Th_Hash;
+typedef struct Th_HashEntry Th_HashEntry;
+struct Th_HashEntry {
+ void *pData;
+ char *zKey;
+ int nKey;
+ Th_HashEntry *pNext; /* Internal use only */
+};
+Th_Hash *Th_HashNew(Th_Interp *);
+void Th_HashDelete(Th_Interp *, Th_Hash *);
+void Th_HashIterate(Th_Interp*,Th_Hash*,int (*x)(Th_HashEntry*, void*),void*);
+Th_HashEntry *Th_HashFind(Th_Interp*, Th_Hash*, const char*, int, int);
+
+/*
+** Useful functions from th_lang.c.
+*/
+int Th_WrongNumArgs(Th_Interp *interp, const char *zMsg);
+
+typedef struct Th_SubCommand {const char *zName; Th_CommandProc xProc;} Th_SubCommand;
+int Th_CallSubCommand(Th_Interp*,void*,int,const char**,int*,const Th_SubCommand*);