|
1
|
/* This header file defines the external interface to the custom Scripting |
|
2
|
** Language (TH) interpreter. TH is very similar to Tcl but is not an |
|
3
|
** exact clone. |
|
4
|
** |
|
5
|
** TH1 was original developed to run SQLite tests on SymbianOS. This version |
|
6
|
** of TH1 was repurposed as a scripted language for Fossil, and was heavily |
|
7
|
** modified for that purpose, beginning in early 2008. |
|
8
|
** |
|
9
|
** More recently, TH1 has been enhanced to distinguish between regular text |
|
10
|
** and "tainted" text. "Tainted" text is text that might have originated |
|
11
|
** from an outside source and hence might not be trustworthy. To prevent |
|
12
|
** cross-site scripting (XSS) and SQL-injections and similar attacks, |
|
13
|
** tainted text should not be used for the following purposes: |
|
14
|
** |
|
15
|
** * executed as TH1 script or expression. |
|
16
|
** * output as HTML or Javascript |
|
17
|
** * used as part of an SQL query |
|
18
|
** |
|
19
|
** Tainted text can be converted into a safe form using commands like |
|
20
|
** "htmlize". And some commands ("query" and "expr") know how to use |
|
21
|
** potentially tainted variable values directly, and thus can bypass |
|
22
|
** the restrictions above. |
|
23
|
** |
|
24
|
** Whether a string is clean or tainted is determined by its length integer. |
|
25
|
** TH1 limits strings to be no more than 0x0fffffff bytes bytes in length |
|
26
|
** (about 268MB - more than sufficient for the purposes of Fossil). The top |
|
27
|
** bit of the length integer is the sign bit, of course. The next three bits |
|
28
|
** are reserved. One of those, the 0x10000000 bit, marks tainted strings. |
|
29
|
*/ |
|
30
|
#define TH1_MX_STRLEN 0x0fffffff /* Maximum length of a TH1-C string */ |
|
31
|
#define TH1_TAINT_BIT 0x10000000 /* The taint bit */ |
|
32
|
#define TH1_SIGN 0x80000000 |
|
33
|
|
|
34
|
/* Convert an integer into a string length. Negative values remain negative */ |
|
35
|
#define TH1_LEN(X) ((TH1_SIGN|TH1_MX_STRLEN)&(X)) |
|
36
|
|
|
37
|
/* Return true if the string is tainted */ |
|
38
|
#define TH1_TAINTED(X) (((X)&TH1_TAINT_BIT)!=0) |
|
39
|
|
|
40
|
/* Remove taint from a string */ |
|
41
|
#define TH1_RM_TAINT(X) ((X)&~TH1_TAINT_BIT) |
|
42
|
|
|
43
|
/* Add taint to a string */ |
|
44
|
#define TH1_ADD_TAINT(X) ((X)|TH1_TAINT_BIT) |
|
45
|
|
|
46
|
/* If B is tainted, make A tainted too */ |
|
47
|
#define TH1_XFER_TAINT(A,B) (A)|=(TH1_TAINT_BIT&(B)) |
|
48
|
|
|
49
|
/* Check to see if a string is too big for TH1 */ |
|
50
|
#define TH1_SIZECHECK(N) if((N)>TH1_MX_STRLEN){Th_OversizeString();} |
|
51
|
void Th_OversizeString(void); |
|
52
|
|
|
53
|
/* |
|
54
|
** Before creating an interpreter, the application must allocate and |
|
55
|
** populate an instance of the following structure. It must remain valid |
|
56
|
** for the lifetime of the interpreter. |
|
57
|
*/ |
|
58
|
typedef struct Th_Vtab Th_Vtab; |
|
59
|
struct Th_Vtab { |
|
60
|
void *(*xMalloc)(unsigned int); |
|
61
|
void (*xFree)(void *); |
|
62
|
}; |
|
63
|
|
|
64
|
/* |
|
65
|
** Opaque handle for interpeter. |
|
66
|
*/ |
|
67
|
typedef struct Th_Interp Th_Interp; |
|
68
|
|
|
69
|
/* |
|
70
|
** Create and delete interpreters. |
|
71
|
*/ |
|
72
|
Th_Interp * Th_CreateInterp(Th_Vtab *); |
|
73
|
void Th_DeleteInterp(Th_Interp *); |
|
74
|
|
|
75
|
/* |
|
76
|
** Report taint in the string zStr,nStr. That string represents "zTitle" |
|
77
|
** If non-zero is returned error out of the caller. |
|
78
|
*/ |
|
79
|
int Th_ReportTaint(Th_Interp*,const char*,const char*zStr,int nStr); |
|
80
|
|
|
81
|
/* |
|
82
|
** Evaluate an TH program in the stack frame identified by parameter |
|
83
|
** iFrame, according to the following rules: |
|
84
|
** |
|
85
|
** * If iFrame is 0, this means the current frame. |
|
86
|
** |
|
87
|
** * If iFrame is negative, then the nth frame up the stack, where n is |
|
88
|
** the absolute value of iFrame. A value of -1 means the calling |
|
89
|
** procedure. |
|
90
|
** |
|
91
|
** * If iFrame is +ve, then the nth frame from the bottom of the stack. |
|
92
|
** An iFrame value of 1 means the toplevel (global) frame. |
|
93
|
*/ |
|
94
|
int Th_Eval(Th_Interp *interp, int iFrame, const char *zProg, int nProg); |
|
95
|
|
|
96
|
/* |
|
97
|
** Evaluate a TH expression. The result is stored in the |
|
98
|
** interpreter result. |
|
99
|
*/ |
|
100
|
int Th_Expr(Th_Interp *interp, const char *, int); |
|
101
|
|
|
102
|
/* |
|
103
|
** Access TH variables in the current stack frame. If the variable name |
|
104
|
** begins with "::", the lookup is in the top level (global) frame. |
|
105
|
*/ |
|
106
|
int Th_ExistsVar(Th_Interp *, const char *, int); |
|
107
|
int Th_ExistsArrayVar(Th_Interp *, const char *, int); |
|
108
|
int Th_GetVar(Th_Interp *, const char *, int); |
|
109
|
int Th_SetVar(Th_Interp *, const char *, int, const char *, int); |
|
110
|
int Th_LinkVar(Th_Interp *, const char *, int, int, const char *, int); |
|
111
|
int Th_UnsetVar(Th_Interp *, const char *, int); |
|
112
|
|
|
113
|
typedef int (*Th_CommandProc)(Th_Interp *, void *, int, const char **, int *); |
|
114
|
|
|
115
|
/* |
|
116
|
** Register new commands. |
|
117
|
*/ |
|
118
|
int Th_CreateCommand( |
|
119
|
Th_Interp *interp, |
|
120
|
const char *zName, |
|
121
|
/* int (*xProc)(Th_Interp *, void *, int, const char **, int *), */ |
|
122
|
Th_CommandProc xProc, |
|
123
|
void *pContext, |
|
124
|
void (*xDel)(Th_Interp *, void *) |
|
125
|
); |
|
126
|
|
|
127
|
/* |
|
128
|
** Delete or rename commands. |
|
129
|
*/ |
|
130
|
int Th_RenameCommand(Th_Interp *, const char *, int, const char *, int); |
|
131
|
|
|
132
|
/* |
|
133
|
** Push a new stack frame (local variable context) onto the interpreter |
|
134
|
** stack, call the function supplied as parameter xCall with the two |
|
135
|
** context arguments, |
|
136
|
** |
|
137
|
** xCall(interp, pContext1, pContext2) |
|
138
|
** |
|
139
|
** , then pop the frame off of the interpreter stack. The value returned |
|
140
|
** by the xCall() function is returned as the result of this function. |
|
141
|
** |
|
142
|
** This is intended for use by the implementation of commands such as |
|
143
|
** those created by [proc]. |
|
144
|
*/ |
|
145
|
int Th_InFrame(Th_Interp *interp, |
|
146
|
int (*xCall)(Th_Interp *, void *pContext1, void *pContext2), |
|
147
|
void *pContext1, |
|
148
|
void *pContext2 |
|
149
|
); |
|
150
|
|
|
151
|
/* |
|
152
|
** Valid return codes for xProc callbacks. |
|
153
|
*/ |
|
154
|
#define TH_OK 0 |
|
155
|
#define TH_ERROR 1 |
|
156
|
#define TH_BREAK 2 |
|
157
|
#define TH_RETURN 3 |
|
158
|
#define TH_CONTINUE 4 |
|
159
|
#define TH_RETURN2 5 |
|
160
|
|
|
161
|
/* |
|
162
|
** Set and get the interpreter result. |
|
163
|
*/ |
|
164
|
int Th_SetResult(Th_Interp *, const char *, int); |
|
165
|
const char *Th_GetResult(Th_Interp *, int *); |
|
166
|
char *Th_TakeResult(Th_Interp *, int *); |
|
167
|
|
|
168
|
/* |
|
169
|
** Set an error message as the interpreter result. This also |
|
170
|
** sets the global stack-trace variable $::th_stack_trace. |
|
171
|
*/ |
|
172
|
int Th_ErrorMessage(Th_Interp *, const char *, const char *, int); |
|
173
|
|
|
174
|
/* |
|
175
|
** Access the memory management functions associated with the specified |
|
176
|
** interpreter. |
|
177
|
*/ |
|
178
|
#if defined(TH_MEMDEBUG) |
|
179
|
void *Th_DbgMalloc(Th_Interp *, int); |
|
180
|
void Th_DbgFree(Th_Interp *, void *); |
|
181
|
#endif |
|
182
|
|
|
183
|
void *fossil_malloc_zero(size_t); |
|
184
|
void *fossil_realloc(void *, size_t); |
|
185
|
void fossil_free(void *); |
|
186
|
|
|
187
|
#define Th_SysMalloc(I,N) fossil_malloc_zero((N)) |
|
188
|
#define Th_SysRealloc(I,P,N) fossil_realloc((P),(N)) |
|
189
|
#define Th_SysFree(I,P) fossil_free((P)) |
|
190
|
|
|
191
|
#if defined(TH_MEMDEBUG) |
|
192
|
# define Th_Malloc(I,N) Th_DbgMalloc((I),(N)) |
|
193
|
# define Th_Free(I,P) Th_DbgFree((I),(P)) |
|
194
|
#else |
|
195
|
# define Th_Malloc(I,N) Th_SysMalloc((I),(N)) |
|
196
|
# define Th_Realloc(I,P,N) Th_SysRealloc((I),(P),(N)) |
|
197
|
# define Th_Free(I,P) Th_SysFree((I),(P)) |
|
198
|
#endif |
|
199
|
|
|
200
|
/* |
|
201
|
** Functions for handling TH lists. |
|
202
|
*/ |
|
203
|
int Th_ListAppend(Th_Interp *, char **, int *, const char *, int); |
|
204
|
int Th_SplitList(Th_Interp *, const char *, int, char ***, int **, int *); |
|
205
|
|
|
206
|
int Th_StringAppend(Th_Interp *, char **, int *, const char *, int); |
|
207
|
|
|
208
|
/* |
|
209
|
** Functions for handling numbers and pointers. |
|
210
|
*/ |
|
211
|
int Th_ToInt(Th_Interp *, const char *, int, int *); |
|
212
|
int Th_ToDouble(Th_Interp *, const char *, int, double *); |
|
213
|
int Th_SetResultInt(Th_Interp *, int); |
|
214
|
int Th_SetResultDouble(Th_Interp *, double); |
|
215
|
|
|
216
|
/* |
|
217
|
** Functions for handling command and variable introspection. |
|
218
|
*/ |
|
219
|
int Th_ListAppendCommands(Th_Interp *, char **, int *); |
|
220
|
int Th_ListAppendVariables(Th_Interp *, char **, int *); |
|
221
|
int Th_ListAppendArray(Th_Interp *, const char *, int, char **, int *); |
|
222
|
|
|
223
|
/* |
|
224
|
** Drop in replacements for the corresponding standard library functions. |
|
225
|
*/ |
|
226
|
int th_strlen(const char *); |
|
227
|
int th_isdigit(char); |
|
228
|
int th_isspace(char); |
|
229
|
int th_isalnum(char); |
|
230
|
int th_isalpha(char); |
|
231
|
int th_isspecial(char); |
|
232
|
int th_ishexdig(char); |
|
233
|
int th_isoctdig(char); |
|
234
|
int th_isbindig(char); |
|
235
|
char *th_strdup(Th_Interp *interp, const char *z, int n); |
|
236
|
|
|
237
|
/* |
|
238
|
** Interfaces to register the language extensions. |
|
239
|
*/ |
|
240
|
int th_register_language(Th_Interp *interp); /* th_lang.c */ |
|
241
|
int th_register_sqlite(Th_Interp *interp); /* th_sqlite.c */ |
|
242
|
int th_register_vfs(Th_Interp *interp); /* th_vfs.c */ |
|
243
|
int th_register_testvfs(Th_Interp *interp); /* th_testvfs.c */ |
|
244
|
|
|
245
|
#ifdef FOSSIL_ENABLE_TCL |
|
246
|
/* |
|
247
|
** Interfaces to the full Tcl core library from "th_tcl.c". |
|
248
|
*/ |
|
249
|
int th_register_tcl(Th_Interp *, void *); |
|
250
|
int unloadTcl(Th_Interp *, void *); |
|
251
|
int evaluateTclWithEvents(Th_Interp *,void *,const char *,int,int,int,int); |
|
252
|
#endif |
|
253
|
|
|
254
|
/* |
|
255
|
** General purpose hash table from th_lang.c. |
|
256
|
*/ |
|
257
|
typedef struct Th_Hash Th_Hash; |
|
258
|
typedef struct Th_HashEntry Th_HashEntry; |
|
259
|
struct Th_HashEntry { |
|
260
|
void *pData; |
|
261
|
char *zKey; |
|
262
|
int nKey; |
|
263
|
Th_HashEntry *pNext; /* Internal use only */ |
|
264
|
}; |
|
265
|
Th_Hash *Th_HashNew(Th_Interp *); |
|
266
|
void Th_HashDelete(Th_Interp *, Th_Hash *); |
|
267
|
void Th_HashIterate(Th_Interp*,Th_Hash*,int (*x)(Th_HashEntry*, void*),void*); |
|
268
|
Th_HashEntry *Th_HashFind(Th_Interp*, Th_Hash*, const char*, int, int); |
|
269
|
|
|
270
|
/* |
|
271
|
** Useful functions from th_lang.c. |
|
272
|
*/ |
|
273
|
int Th_WrongNumArgs(Th_Interp *interp, const char *zMsg); |
|
274
|
|
|
275
|
typedef struct Th_SubCommand {const char *zName; Th_CommandProc xProc;} Th_SubCommand; |
|
276
|
int Th_CallSubCommand(Th_Interp*,void*,int,const char**,int*,const Th_SubCommand*); |
|
277
|
|