From ebefc48e61a7d5cf2a3228e6c8729feeeb42d1b4 Mon Sep 17 00:00:00 2001 From: David 'Digit' Turner Date: Fri, 29 May 2009 14:45:04 +0200 Subject: [PATCH 1/4] Expose the stable/frozen log-related definitions of into a new header: This is in order to expose the correponding functions in the 1.5 Native Development Kit, to allow applicative native code to send messages to the log. --- include/android/log.h | 128 ++++++++++++++++++++++++++++++++++++++++++ include/cutils/logd.h | 43 +++----------- 2 files changed, 135 insertions(+), 36 deletions(-) create mode 100644 include/android/log.h diff --git a/include/android/log.h b/include/android/log.h new file mode 100644 index 000000000..0ea4c298b --- /dev/null +++ b/include/android/log.h @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _ANDROID_LOG_H +#define _ANDROID_LOG_H + +/****************************************************************** + * + * IMPORTANT NOTICE: + * + * This file is part of Android's set of stable system headers + * exposed by the Android NDK (Native Development Kit) since + * platform release 1.5 + * + * Third-party source AND binary code relies on the definitions + * here to be FROZEN ON ALL UPCOMING PLATFORM RELEASES. + * + * - DO NOT MODIFY ENUMS (EXCEPT IF YOU ADD NEW 32-BIT VALUES) + * - DO NOT MODIFY CONSTANTS OR FUNCTIONAL MACROS + * - DO NOT CHANGE THE SIGNATURE OF FUNCTIONS IN ANY WAY + * - DO NOT CHANGE THE LAYOUT OR SIZE OF STRUCTURES + */ + +/* + * Support routines to send messages to the Android in-kernel log buffer, + * which can later be accessed through the 'logcat' utility. + * + * Each log message must have + * - a priority + * - a log tag + * - some text + * + * The tag normally corresponds to the component that emits the log message, + * and should be reasonably small. + * + * Log message text may be truncated to less than an implementation-specific + * limit (e.g. 1023 characters max). + * + * Note that a newline character ("\n") will be appended automatically to your + * log message, if not already there. It is not possible to send several messages + * and have them appear on a single line in logcat. + * + * PLEASE USE LOGS WITH MODERATION: + * + * - Sending log messages eats CPU and slow down your application and the + * system. + * + * - The circular log buffer is pretty small (<64KB), sending many messages + * might push off other important log messages from the rest of the system. + * + * - In release builds, only send log messages to account for exceptional + * conditions. + * + * NOTE: These functions MUST be implemented by /system/lib/liblog.so + */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Android log priority values, in ascending priority order. + */ +typedef enum android_LogPriority { + ANDROID_LOG_UNKNOWN = 0, + ANDROID_LOG_DEFAULT, /* only for SetMinPriority() */ + ANDROID_LOG_VERBOSE, + ANDROID_LOG_DEBUG, + ANDROID_LOG_INFO, + ANDROID_LOG_WARN, + ANDROID_LOG_ERROR, + ANDROID_LOG_FATAL, + ANDROID_LOG_SILENT, /* only for SetMinPriority(); must be last */ +} android_LogPriority; + +/* + * Send a simple string to the log. + */ +int __android_log_write(int prio, const char *tag, const char *text); + +/* + * Send a formatted string to the log, used like printf(fmt,...) + */ +int __android_log_print(int prio, const char *tag, const char *fmt, ...) +#if defined(__GNUC__) + __attribute__ ((format(printf, 3, 4))) +#endif + ; + +/* + * A variant of __android_log_print() that takes a va_list to list + * additional parameters. + */ +int __android_log_vprint(int prio, const char *tag, + const char *fmt, va_list ap); + +/* + * Log an assertion failure and SIGTRAP the process to have a chance + * to inspect it, if a debugger is attached. This uses the FATAL priority. + */ +void __android_log_assert(const char *cond, const char *tag, + const char *fmt, ...) +#if defined(__GNUC__) + __attribute__ ((noreturn)) + __attribute__ ((format(printf, 3, 4))) +#endif + ; + +#ifdef __cplusplus +} +#endif + +#endif /* _ANDROID_LOG_H */ diff --git a/include/cutils/logd.h b/include/cutils/logd.h index a1cb012c7..8737639cc 100644 --- a/include/cutils/logd.h +++ b/include/cutils/logd.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 The Android Open Source Project + * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,12 @@ #ifndef _ANDROID_CUTILS_LOGD_H #define _ANDROID_CUTILS_LOGD_H +/* the stable/frozen log-related definitions have been + * moved to this header, which is exposed by the NDK + */ +#include + +/* the rest is only used internally by the system */ #include #include #include @@ -32,45 +38,10 @@ extern "C" { #endif -/* - * Priority values, in ascending priority order. - */ -typedef enum android_LogPriority { - ANDROID_LOG_UNKNOWN = 0, - ANDROID_LOG_DEFAULT, /* only for SetMinPriority() */ - ANDROID_LOG_VERBOSE, - ANDROID_LOG_DEBUG, - ANDROID_LOG_INFO, - ANDROID_LOG_WARN, - ANDROID_LOG_ERROR, - ANDROID_LOG_FATAL, - ANDROID_LOG_SILENT, /* only for SetMinPriority(); must be last */ -} android_LogPriority; - -int __android_log_write(int prio, const char *tag, const char *text); - -int __android_log_vprint(int prio, const char *tag, - const char *fmt, va_list ap); - int __android_log_bwrite(int32_t tag, const void *payload, size_t len); int __android_log_btwrite(int32_t tag, char type, const void *payload, size_t len); -int __android_log_print(int prio, const char *tag, const char *fmt, ...) -#if defined(__GNUC__) - __attribute__ ((format(printf, 3, 4))) -#endif - ; - - -void __android_log_assert(const char *cond, const char *tag, - const char *fmt, ...) -#if defined(__GNUC__) - __attribute__ ((noreturn)) - __attribute__ ((format(printf, 3, 4))) -#endif - ; - #ifdef __cplusplus } #endif From 653f42da9249a2f576d1ff50ee22bf6a67ff90b1 Mon Sep 17 00:00:00 2001 From: Jack Palevich Date: Thu, 28 May 2009 17:15:32 -0700 Subject: [PATCH 2/4] Pointer-ize the acc front end. The ACC compiler used to be able to compile itself. This was a neat feature, but because ACC only supports ints, pointers are stored as ints, and cast to pointers when used. This checkin turns many ints that are really pointers back into pointers, so that the code is clearer. int ch; char* glo; char* sym_stack; char* dstk; char* dptr; int dch; char* last_id; --- libacc/acc.cpp | 93 +++++++++++++++++++++++++------------------------- 1 file changed, 47 insertions(+), 46 deletions(-) diff --git a/libacc/acc.cpp b/libacc/acc.cpp index b7e45942e..45f0c732e 100644 --- a/libacc/acc.cpp +++ b/libacc/acc.cpp @@ -47,7 +47,7 @@ namespace acc { class Compiler { class CodeBuf { - char* ind; + char* ind; // Output code pointer char* pProgramBase; void release() { @@ -1027,20 +1027,21 @@ class Compiler { size_t mPosition; }; - /* vars: value of variables - loc : local variable index - glo : global variable index - ind : output code ptr - rsym: return symbol - prog: output code - dstk: define stack - dptr, dch: macro state - */ - intptr_t tok, tokc, tokl, ch, vars, rsym, loc, glo, sym_stk, dstk, - dptr, dch, last_id; + int ch; // Current input character, or EOF + intptr_t tok; // token + intptr_t tokc; // token extra info + int tokl; // token operator level + intptr_t rsym; // return symbol + intptr_t loc; // local variable index + char* glo; // global variable index + char* sym_stk; + char* dstk; // Define stack + char* dptr; // Macro state: Points to macro text during macro playback. + int dch; // Macro state: Saves old value of ch during a macro playback. + char* last_id; void* pSymbolBase; void* pGlobalBase; - void* pVarsBase; + char* pVarsBase; // Value of variables InputStream* file; @@ -1106,12 +1107,12 @@ class Compiler { static const char operatorLevel[]; void pdef(int t) { - *(char *) dstk++ = t; + *dstk++ = t; } void inp() { if (dptr) { - ch = *(char *) dptr++; + ch = *dptr++; if (ch == TAG_MACRO) { dptr = 0; ch = dch; @@ -1145,7 +1146,7 @@ class Compiler { next(); pdef(TAG_TOK); /* fill last ident tag */ *(int *) tok = SYM_DEFINE; - *(int *) (tok + 4) = dstk; /* define stack */ + *(char* *) (tok + 4) = dstk; /* define stack */ } /* well we always save the values ! */ while (ch != '\n') { @@ -1168,21 +1169,21 @@ class Compiler { inp(); } if (isdigit(tok)) { - tokc = strtol((char*) last_id, 0, 0); + tokc = strtol(last_id, 0, 0); tok = TOK_NUM; } else { - *(char *) dstk = TAG_TOK; /* no need to mark end of string (we + * dstk = TAG_TOK; /* no need to mark end of string (we suppose data is initialized to zero by calloc) */ - tok = (intptr_t) (strstr((char*) sym_stk, (char*) (last_id - 1)) + tok = (intptr_t) (strstr(sym_stk, (last_id - 1)) - sym_stk); - *(char *) dstk = 0; /* mark real end of ident for dlsym() */ + * dstk = 0; /* mark real end of ident for dlsym() */ tok = tok * 8 + TOK_IDENT; if (tok > TOK_DEFINE) { - tok = vars + tok; + tok = (intptr_t) (pVarsBase + tok); /* printf("tok=%s %x\n", last_id, tok); */ /* define handling */ if (*(int *) tok == SYM_DEFINE) { - dptr = *(int *) (tok + 4); + dptr = *(char* *) (tok + 4); dch = ch; inp(); next(); @@ -1243,17 +1244,17 @@ class Compiler { } #if 0 { - int p; + char* p; printf("tok=0x%x ", tok); if (tok >= TOK_IDENT) { printf("'"); if (tok> TOK_DEFINE) - p = sym_stk + 1 + (tok - vars - TOK_IDENT) / 8; + p = sym_stk + 1 + ((char*) tok - pVarsBase - TOK_IDENT) / 8; else p = sym_stk + 1 + (tok - TOK_IDENT) / 8; - while (*(char *)p != TAG_TOK && *(char *)p) - printf("%c", *(char *)p++); + while (*p != TAG_TOK && *p) + printf("%c", *p++); printf("'\n"); } else if (tok == TOK_NUM) { printf("%d\n", tokc); @@ -1284,19 +1285,20 @@ class Compiler { /* l is one if '=' parsing wanted (quick hack) */ void unary(intptr_t l) { - intptr_t n, t, a, c; + intptr_t n, t, a; + int c; t = 0; n = 1; /* type of expression 0 = forward, 1 = value, other = lvalue */ if (tok == '\"') { - pGen->li(glo); + pGen->li((int) glo); while (ch != '\"') { getq(); - *(char *) glo++ = ch; + *glo++ = ch; inp(); } - *(char *) glo = 0; - glo = (glo + 4) & -4; /* align heap */ + *glo = 0; + glo = (char*) (((intptr_t) glo + 4) & -4); /* align heap */ inp(); next(); } else { @@ -1349,7 +1351,7 @@ class Compiler { n = *(int *) t; /* forward reference: try dlsym */ if (!n) { - n = (intptr_t) dlsym(RTLD_DEFAULT, (char*) last_id); + n = (intptr_t) dlsym(RTLD_DEFAULT, last_id); } if ((tok == '=') & l) { /* assignment */ @@ -1398,7 +1400,7 @@ class Compiler { } } - void sum(intptr_t l) { + void sum(int l) { intptr_t t, n, a; t = 0; if (l-- == 1) @@ -1518,7 +1520,7 @@ class Compiler { void decl(bool l) { intptr_t a; - while ((tok == TOK_INT) | ((tok != -1) & (!l))) { + while ((tok == TOK_INT) | ((tok != EOF) & (!l))) { if (tok == TOK_INT) { next(); while (tok != ';') { @@ -1526,7 +1528,7 @@ class Compiler { loc = loc + 4; *(int *) tok = -loc; } else { - *(int *) tok = glo; + *(int* *) tok = (int*) glo; glo = glo + 4; } next(); @@ -1565,7 +1567,7 @@ class Compiler { void cleanup() { if (sym_stk != 0) { - free((void*) sym_stk); + free(sym_stk); sym_stk = 0; } if (pGlobalBase != 0) { @@ -1591,7 +1593,7 @@ class Compiler { tokc = 0; tokl = 0; ch = 0; - vars = 0; + pVarsBase = 0; rsym = 0; loc = 0; glo = 0; @@ -1664,14 +1666,13 @@ public: } pGen->init(&codeBuf); file = new TextInputStream(text, textLength); - sym_stk = (intptr_t) calloc(1, ALLOC_SIZE); - dstk = (intptr_t) strcpy((char*) sym_stk, + sym_stk = (char*) calloc(1, ALLOC_SIZE); + dstk = strcpy(sym_stk, " int if else while break return for define main ") + TOK_STR_SIZE; pGlobalBase = calloc(1, ALLOC_SIZE); - glo = (intptr_t) pGlobalBase; - pVarsBase = calloc(1, ALLOC_SIZE); - vars = (intptr_t) pVarsBase; + glo = (char*) pGlobalBase; + pVarsBase = (char*) calloc(1, ALLOC_SIZE); inp(); next(); decl(0); @@ -1681,7 +1682,7 @@ public: int run(int argc, char** argv) { typedef int (*mainPtr)(int argc, char** argv); - mainPtr aMain = (mainPtr) *(int*) (vars + TOK_MAIN); + mainPtr aMain = (mainPtr) *(int*) (pVarsBase + TOK_MAIN); if (!aMain) { fprintf(stderr, "Could not find function \"main\".\n"); return -1; @@ -1706,7 +1707,7 @@ public: return NULL; } size_t nameLen = strlen(name); - char* pSym = (char*) sym_stk; + char* pSym = sym_stk; char c; for(;;) { c = *pSym++; @@ -1716,12 +1717,12 @@ public: if (c == TAG_TOK) { if (memcmp(pSym, name, nameLen) == 0 && pSym[nameLen] == TAG_TOK) { - int tok = pSym - 1 - (char*) sym_stk; + int tok = pSym - 1 - sym_stk; tok = tok * 8 + TOK_IDENT; if (tok <= TOK_DEFINE) { return 0; } else { - tok = vars + tok; + tok = (intptr_t) (pVarsBase + tok); return * (void**) tok; } } From ac0e95eb60fc8f8ef3281f9183630d1515bd12a7 Mon Sep 17 00:00:00 2001 From: Jack Palevich Date: Fri, 29 May 2009 13:53:44 -0700 Subject: [PATCH 3/4] Improve ACC error reporting. Now return an error code and an error message, rather than just printing to stderr or calling exit(). Check to see we don't exceed our code size. --- libacc/acc.cpp | 162 +++++++++++++++++++++++++++----------- libacc/tests/data/error.c | 2 + libacc/tests/main.cpp | 12 ++- 3 files changed, 128 insertions(+), 48 deletions(-) create mode 100644 libacc/tests/data/error.c diff --git a/libacc/acc.cpp b/libacc/acc.cpp index 45f0c732e..0587dd968 100644 --- a/libacc/acc.cpp +++ b/libacc/acc.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -45,10 +46,24 @@ namespace acc { -class Compiler { +class ErrorSink { +public: + void error(const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + verror(fmt, ap); + va_end(ap); + } + + virtual void verror(const char* fmt, va_list ap) = 0; +}; + +class Compiler : public ErrorSink { class CodeBuf { char* ind; // Output code pointer char* pProgramBase; + ErrorSink* mErrorSink; + int mSize; void release() { if (pProgramBase != 0) { @@ -57,10 +72,21 @@ class Compiler { } } + void check(int n) { + int newSize = ind - pProgramBase + n; + if (newSize > mSize) { + if (mErrorSink) { + mErrorSink->error("Code too large: %d bytes", newSize); + } + } + } + public: CodeBuf() { pProgramBase = 0; ind = 0; + mErrorSink = 0; + mSize = 0; } ~CodeBuf() { @@ -69,11 +95,17 @@ class Compiler { void init(int size) { release(); + mSize = size; pProgramBase = (char*) calloc(1, size); ind = pProgramBase; } + void setErrorSink(ErrorSink* pErrorSink) { + mErrorSink = pErrorSink; + } + int o4(int n) { + check(4); intptr_t result = (intptr_t) ind; * (int*) ind = n; ind += 4; @@ -84,6 +116,7 @@ class Compiler { * Output a byte. Handles all values, 0..ff. */ void ob(int n) { + check(1); *ind++ = n; } @@ -123,11 +156,22 @@ class Compiler { class CodeGenerator { public: - CodeGenerator() {} + CodeGenerator() { + mErrorSink = 0; + pCodeBuf = 0; + } virtual ~CodeGenerator() {} virtual void init(CodeBuf* pCodeBuf) { this->pCodeBuf = pCodeBuf; + pCodeBuf->setErrorSink(mErrorSink); + } + + void setErrorSink(ErrorSink* pErrorSink) { + mErrorSink = pErrorSink; + if (pCodeBuf) { + pCodeBuf->setErrorSink(mErrorSink); + } } /* Emit a function prolog. @@ -323,8 +367,16 @@ class Compiler { intptr_t getSize() { return pCodeBuf->getSize(); } + + void error(const char* fmt,...) { + va_list ap; + va_start(ap, fmt); + mErrorSink->verror(fmt, ap); + va_end(ap); + } private: CodeBuf* pCodeBuf; + ErrorSink* mErrorSink; }; #ifdef PROVIDE_ARM_CODEGEN @@ -643,7 +695,7 @@ class Compiler { virtual void callRelative(int t) { LOG_API("callRelative(%d);\n", t); int abs = t + getPC() + jumpOffset(); - fprintf(stderr, "abs=%d (0x%08x)\n", abs, abs); + LOG_API("abs=%d (0x%08x)\n", abs, abs); if (t >= - (1 << 25) && t < (1 << 25)) { o4(0xEB000000 | encodeAddress(t)); } else { @@ -791,14 +843,6 @@ class Compiler { static int runtime_MOD(int a, int b) { return b % a; } - - void error(const char* fmt,...) { - va_list ap; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - exit(12); - } }; #endif // PROVIDE_ARM_CODEGEN @@ -980,8 +1024,7 @@ class Compiler { int decodeOp(int op) { if (op < 0 || op > OP_COUNT) { - fprintf(stderr, "Out-of-range operator: %d\n", op); - exit(1); + error("Out-of-range operator: %d\n", op); } return operatorHelper[op]; } @@ -1048,6 +1091,10 @@ class Compiler { CodeBuf codeBuf; CodeGenerator* pGen; + static const int ERROR_BUF_SIZE = 512; + char mErrorBuf[ERROR_BUF_SIZE]; + jmp_buf mErrorRecoveryJumpBuf; + static const int ALLOC_SIZE = 99999; /* depends on the init string */ @@ -1265,15 +1312,24 @@ class Compiler { #endif } - void error(const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - fprintf(stderr, "%ld: ", file->tell()); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); - va_end(ap); - exit(1); + virtual void verror(const char* fmt, va_list ap) { + char* pBase = mErrorBuf; + int bytesLeft = sizeof(mErrorBuf); + int bytesAdded = snprintf(pBase, bytesLeft, "%ld: ", file->tell()); + bytesLeft -= bytesAdded; + pBase += bytesAdded; + if (bytesLeft > 0) { + bytesAdded = vsnprintf(pBase, bytesLeft, fmt, ap); + bytesLeft -= bytesAdded; + pBase += bytesAdded; + } + if (bytesLeft > 0) { + bytesAdded = snprintf(pBase, bytesLeft, "\n"); + bytesLeft -= bytesAdded; + pBase += bytesAdded; + } + longjmp(mErrorRecoveryJumpBuf, 1); } void skip(intptr_t c) { @@ -1606,6 +1662,7 @@ class Compiler { pGlobalBase = 0; pVarsBase = 0; pGen = 0; + mErrorBuf[0] = 0; } void setArchitecture(const char* architecture) { @@ -1624,7 +1681,7 @@ class Compiler { } #endif if (!pGen ) { - fprintf(stderr, "Unknown architecture %s\n", architecture); + error("Unknown architecture %s\n", architecture); } } @@ -1636,8 +1693,9 @@ class Compiler { #endif } if (pGen == NULL) { - fprintf(stderr, "No code generator defined.\n"); + error("No code generator defined."); } + pGen->setErrorSink(this); } public: @@ -1657,27 +1715,30 @@ public: } int compile(const char* text, size_t textLength) { - cleanup(); - clear(); - codeBuf.init(ALLOC_SIZE); - setArchitecture(NULL); - if (!pGen) { - return -1; + int result; + if (! (result = setjmp(mErrorRecoveryJumpBuf))) { + cleanup(); + clear(); + codeBuf.init(ALLOC_SIZE); + setArchitecture(NULL); + if (!pGen) { + return -1; + } + pGen->init(&codeBuf); + file = new TextInputStream(text, textLength); + sym_stk = (char*) calloc(1, ALLOC_SIZE); + dstk = strcpy(sym_stk, + " int if else while break return for define main ") + + TOK_STR_SIZE; + pGlobalBase = calloc(1, ALLOC_SIZE); + glo = (char*) pGlobalBase; + pVarsBase = (char*) calloc(1, ALLOC_SIZE); + inp(); + next(); + decl(0); + pGen->finishCompile(); } - pGen->init(&codeBuf); - file = new TextInputStream(text, textLength); - sym_stk = (char*) calloc(1, ALLOC_SIZE); - dstk = strcpy(sym_stk, - " int if else while break return for define main ") - + TOK_STR_SIZE; - pGlobalBase = calloc(1, ALLOC_SIZE); - glo = (char*) pGlobalBase; - pVarsBase = (char*) calloc(1, ALLOC_SIZE); - inp(); - next(); - decl(0); - pGen->finishCompile(); - return 0; + return result; } int run(int argc, char** argv) { @@ -1731,6 +1792,10 @@ public: return NULL; } + char* getErrorMessage() { + return mErrorBuf; + } + }; const char* Compiler::operatorChars = @@ -1881,11 +1946,16 @@ void accGetScriptInfoLog(ACCscript* script, ACCsizei maxLength, ACCsizei * length, ACCchar * infoLog) { + char* message = script->compiler.getErrorMessage(); + int messageLength = strlen(message) + 1; if (length) { - *length = 0; + *length = messageLength; } - if (maxLength > 0 && infoLog) { - *infoLog = 0; + if (infoLog && maxLength > 0) { + int trimmedLength = maxLength < messageLength ? + maxLength : messageLength; + memcpy(infoLog, message, trimmedLength); + infoLog[trimmedLength] = 0; } } diff --git a/libacc/tests/data/error.c b/libacc/tests/data/error.c new file mode 100644 index 000000000..2e08dcc21 --- /dev/null +++ b/libacc/tests/data/error.c @@ -0,0 +1,2 @@ +void foo; + diff --git a/libacc/tests/main.cpp b/libacc/tests/main.cpp index 8cfc1969c..e65103e83 100644 --- a/libacc/tests/main.cpp +++ b/libacc/tests/main.cpp @@ -81,12 +81,18 @@ int main(int argc, char** argv) { delete[] text; accCompileScript(script); - + int result = accGetError(script); MainPtr mainPointer = 0; + if (result != 0) { + char buf[1024]; + accGetScriptInfoLog(script, sizeof(buf), NULL, buf); + fprintf(stderr, "%ss", buf); + goto exit; + } accGetScriptLabel(script, "main", (ACCvoid**) & mainPointer); - int result = accGetError(script); + result = accGetError(script); if (result == ACC_NO_ERROR) { fprintf(stderr, "Executing compiled code:\n"); int codeArgc = argc - i + 1; @@ -96,6 +102,8 @@ int main(int argc, char** argv) { fprintf(stderr, "result: %d\n", result); } +exit: + accDeleteScript(script); return result; From f1f39cca305f6f3d2d91b88736b7b2b520d59e2e Mon Sep 17 00:00:00 2001 From: Jack Palevich Date: Fri, 29 May 2009 18:03:15 -0700 Subject: [PATCH 4/4] Make sure we don't overflow various internal compiler buffers. We may replace some of these tables with dynamically growing data structures, but in the meantime we will not trash memory. --- libacc/acc.cpp | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/libacc/acc.cpp b/libacc/acc.cpp index 0587dd968..733f1880d 100644 --- a/libacc/acc.cpp +++ b/libacc/acc.cpp @@ -1083,7 +1083,7 @@ class Compiler : public ErrorSink { int dch; // Macro state: Saves old value of ch during a macro playback. char* last_id; void* pSymbolBase; - void* pGlobalBase; + char* pGlobalBase; char* pVarsBase; // Value of variables InputStream* file; @@ -1154,6 +1154,9 @@ class Compiler : public ErrorSink { static const char operatorLevel[]; void pdef(int t) { + if (dstk - sym_stk >= ALLOC_SIZE) { + error("Symbol table exhausted"); + } *dstk++ = t; } @@ -1219,6 +1222,9 @@ class Compiler : public ErrorSink { tokc = strtol(last_id, 0, 0); tok = TOK_NUM; } else { + if (dstk - sym_stk + 1 > ALLOC_SIZE) { + error("symbol stack overflow"); + } * dstk = TAG_TOK; /* no need to mark end of string (we suppose data is initialized to zero by calloc) */ tok = (intptr_t) (strstr(sym_stk, (last_id - 1)) @@ -1226,6 +1232,9 @@ class Compiler : public ErrorSink { * dstk = 0; /* mark real end of ident for dlsym() */ tok = tok * 8 + TOK_IDENT; if (tok > TOK_DEFINE) { + if (tok + 8 > ALLOC_SIZE) { + error("Variable Table overflow."); + } tok = (intptr_t) (pVarsBase + tok); /* printf("tok=%s %x\n", last_id, tok); */ /* define handling */ @@ -1350,11 +1359,12 @@ class Compiler : public ErrorSink { pGen->li((int) glo); while (ch != '\"') { getq(); - *glo++ = ch; + *allocGlobalSpace(1) = ch; inp(); } *glo = 0; - glo = (char*) (((intptr_t) glo + 4) & -4); /* align heap */ + /* align heap */ + allocGlobalSpace((char*) (((intptr_t) glo + 4) & -4) - glo); inp(); next(); } else { @@ -1584,8 +1594,7 @@ class Compiler : public ErrorSink { loc = loc + 4; *(int *) tok = -loc; } else { - *(int* *) tok = (int*) glo; - glo = glo + 4; + *(int* *) tok = (int*) allocGlobalSpace(4); } next(); if (tok == ',') @@ -1621,13 +1630,22 @@ class Compiler : public ErrorSink { } } + char* allocGlobalSpace(int bytes) { + if (glo - pGlobalBase + bytes > ALLOC_SIZE) { + error("Global space exhausted"); + } + char* result = glo; + glo += bytes; + return result; + } + void cleanup() { if (sym_stk != 0) { free(sym_stk); sym_stk = 0; } if (pGlobalBase != 0) { - free((void*) pGlobalBase); + free(pGlobalBase); pGlobalBase = 0; } if (pVarsBase != 0) { @@ -1730,8 +1748,8 @@ public: dstk = strcpy(sym_stk, " int if else while break return for define main ") + TOK_STR_SIZE; - pGlobalBase = calloc(1, ALLOC_SIZE); - glo = (char*) pGlobalBase; + pGlobalBase = (char*) calloc(1, ALLOC_SIZE); + glo = pGlobalBase; pVarsBase = (char*) calloc(1, ALLOC_SIZE); inp(); next();