]> git.sur5r.net Git - cc65/commitdiff
Add checks for risky goto statements.
authorLaubzega <mileksmyk@gmail.com>
Fri, 21 Sep 2018 07:40:05 +0000 (00:40 -0700)
committerOliver Schmidt <ol.sc@web.de>
Tue, 2 Oct 2018 16:49:53 +0000 (18:49 +0200)
src/cc65/asmstmt.c
src/cc65/expr.c
src/cc65/function.c
src/cc65/function.h
src/cc65/goto.c
src/cc65/locals.c
src/cc65/stmt.c
src/cc65/symentry.c
src/cc65/symentry.h
src/cc65/symtab.c

index 4dd6628c44a4e719dda499e4fd7742e3e3d568be..1fc4e31676f74fe1b4d0999d1eb5c2ca76d02690 100644 (file)
@@ -238,7 +238,7 @@ static void ParseGVarArg (StrBuf* T, unsigned Arg)
     } else {
         /* Static variable */
         char Buf [16];
-        xsprintf (Buf, sizeof (Buf), "L%04X", Sym->V.Label);
+        xsprintf (Buf, sizeof (Buf), "L%04X", Sym->V.L.Label);
         SB_AppendStr (T, Buf);
     }
 }
@@ -293,7 +293,7 @@ static void ParseLabelArg (StrBuf* T, unsigned Arg attribute ((unused)))
         SymEntry* Entry = AddLabelSym (CurTok.Ident, SC_REF);
 
         /* Append the label name to the buffer */
-        SB_AppendStr (T, LocalLabelName (Entry->V.Label));
+        SB_AppendStr (T, LocalLabelName (Entry->V.L.Label));
 
         /* Eat the label name */
         NextToken ();
index 43971caaefedb6e4a1da1674215df26cbbf0c75c..55c6391d2c4fc16a1ab988cce396bca6b130d783 100644 (file)
@@ -757,7 +757,7 @@ static void Primary (ExprDesc* E)
                         E->Name = (uintptr_t) Sym->Name;
                     } else {
                         E->Flags = E_LOC_STATIC | E_RTYPE_LVAL;
-                        E->Name = Sym->V.Label;
+                        E->Name = Sym->V.L.Label;
                     }
                 } else {
                     /* Local static variable */
index 22b305739cc09816531a15f26ee3e9db43566c32..6a601db2c09ea4170f60dd8dbef11dcdd7aac670 100644 (file)
 /*****************************************************************************/
 
 
-
-/* Enumeration for function flags */
-typedef enum {
-    FF_NONE             = 0x0000,
-    FF_HAS_RETURN       = 0x0001,       /* Function has a return statement */
-    FF_IS_MAIN          = 0x0002,       /* This is the main function */
-    FF_VOID_RETURN      = 0x0004,       /* Function returning void */
-} funcflags_t;
-
-/* Structure that holds all data needed for function activation */
-struct Function {
-    struct SymEntry*    FuncEntry;      /* Symbol table entry */
-    Type*               ReturnType;     /* Function return type */
-    FuncDesc*           Desc;           /* Function descriptor */
-    int                 Reserved;       /* Reserved local space */
-    unsigned            RetLab;         /* Return code label */
-    int                 TopLevelSP;     /* SP at function top level */
-    unsigned            RegOffs;        /* Register variable space offset */
-    funcflags_t         Flags;          /* Function flags */
-};
-
 /* Pointer to current function */
 Function* CurrentFunc = 0;
 
@@ -99,14 +78,17 @@ static Function* NewFunction (struct SymEntry* Sym)
     Function* F = (Function*) xmalloc (sizeof (Function));
 
     /* Initialize the fields */
-    F->FuncEntry  = Sym;
-    F->ReturnType = GetFuncReturn (Sym->Type);
-    F->Desc       = GetFuncDesc (Sym->Type);
-    F->Reserved   = 0;
-    F->RetLab     = GetLocalLabel ();
-    F->TopLevelSP = 0;
-    F->RegOffs    = RegisterSpace;
-    F->Flags      = IsTypeVoid (F->ReturnType) ? FF_VOID_RETURN : FF_NONE;
+    F->FuncEntry        = Sym;
+    F->ReturnType       = GetFuncReturn (Sym->Type);
+    F->Desc             = GetFuncDesc (Sym->Type);
+    F->Reserved         = 0;
+    F->RetLab           = GetLocalLabel ();
+    F->TopLevelSP       = 0;
+    F->RegOffs          = RegisterSpace;
+    F->Flags            = IsTypeVoid (F->ReturnType) ? FF_VOID_RETURN : FF_NONE;
+    F->LocalsBlockCount = 0;
+
+    InitCollection (&F->LocalsBlockStack);
 
     /* Return the new structure */
     return F;
@@ -117,6 +99,7 @@ static Function* NewFunction (struct SymEntry* Sym)
 static void FreeFunction (Function* F)
 /* Free a function activation structure */
 {
+    DoneCollection (&F->LocalsBlockStack);
     xfree (F);
 }
 
index 627457277e0040183a00ea2466115627aaca3a2d..1b04009d66c0ab783272a5f10c246e6d7e1f4a8d 100644 (file)
 #ifndef FUNCTION_H
 #define FUNCTION_H
 
-
+#include "coll.h"
 
 /*****************************************************************************/
-/*                                   data                                    */
+/*                                   Data                                    */
 /*****************************************************************************/
 
 
+/* Enumeration for function flags */
+typedef enum {
+    FF_NONE             = 0x0000,
+    FF_HAS_RETURN       = 0x0001,       /* Function has a return statement */
+    FF_IS_MAIN          = 0x0002,       /* This is the main function */
+    FF_VOID_RETURN      = 0x0004,       /* Function returning void */
+} funcflags_t;
+
+/* Structure that holds all data needed for function activation */
+struct Function {
+    struct SymEntry*    FuncEntry;        /* Symbol table entry */
+    Type*               ReturnType;       /* Function return type */
+    FuncDesc*           Desc;             /* Function descriptor */
+    int                 Reserved;         /* Reserved local space */
+    unsigned            RetLab;           /* Return code label */
+    int                 TopLevelSP;       /* SP at function top level */
+    unsigned            RegOffs;          /* Register variable space offset */
+    funcflags_t         Flags;            /* Function flags */
+    long                LocalsBlockCount; /* Number of blocks with local vars */
+    Collection          LocalsBlockStack; /* Stack of blocks with local vars */
+};
+
+
 
 /* Structure that holds all data needed for function activation */
 typedef struct Function Function;
index 6e282c636adad4ec08adca9da0cabfb78dad94de..3b1d243e76d05b420c2000f800668e85ad74368c 100644 (file)
@@ -64,7 +64,7 @@ void GotoStatement (void)
         SymEntry* Entry = AddLabelSym (CurTok.Ident, SC_REF);
 
         /* Jump to the label */
-        g_jump (Entry->V.Label);
+        g_jump (Entry->V.L.Label);
     }
 
     /* Eat the label name */
@@ -80,7 +80,7 @@ void DoLabel (void)
     SymEntry* Entry = AddLabelSym (CurTok.Ident, SC_DEF);
 
     /* Emit the jump label */
-    g_defcodelabel (Entry->V.Label);
+    g_defcodelabel (Entry->V.L.Label);
 
     /* Eat the ident and colon */
     NextToken ();
index ffadb1bd502f57eb47468fc679d61979a6307758..a231a600349875aaae25e7dd43ec0e26f495ed2f 100644 (file)
@@ -538,6 +538,13 @@ void DeclareLocals (void)
     /* Be sure to allocate any reserved space for locals */
     F_AllocLocalSpace (CurrentFunc);
 
+    if (InitialStack != StackPtr)
+    {
+        ++CurrentFunc->LocalsBlockCount;
+        /* Is it ok to abuse Collection in this way? */
+        CollAppend (&CurrentFunc->LocalsBlockStack, (void *)CurrentFunc->LocalsBlockCount);
+    }
+
     /* In case we've allocated local variables in this block, emit a call to
     ** the stack checking routine if stack checks are enabled.
     */
index c6167fa78cb08d757a7a6cab5ee746144ee448c8..be58e4a7e71767ac0c6a0507e9948dbc7ee77ee3 100644 (file)
@@ -534,6 +534,10 @@ static int CompoundStatement (void)
     if (!GotBreak) {
         g_space (StackPtr - OldStack);
     }
+
+    if (OldStack != StackPtr)
+        CollPop (&CurrentFunc->LocalsBlockStack);
+
     StackPtr = OldStack;
 
     /* Emit references to imports/exports for this block */
index d6e68d1bbbdd291b51d175ba28a600add40acae9..8091c4d265bc187d563d29a7215047ddae229454 100644 (file)
@@ -83,8 +83,21 @@ SymEntry* NewSymEntry (const char* Name, unsigned Flags)
 void FreeSymEntry (SymEntry* E)
 /* Free a symbol entry */
 {
+    unsigned i;
+
     TypeFree (E->Type);
     xfree (E->AsmName);
+
+    if (E->Flags & SC_LABEL)
+    {
+        for (i = 0; i < CollCount (E->V.L.DefsOrRefs); i++)
+        {
+            xfree (CollAt(E->V.L.DefsOrRefs, i));
+        }
+
+        DoneCollection (E->V.L.DefsOrRefs);
+    }
+
     xfree (E);
 }
 
index ff136702f6cfd9849918988ed84aee204e6ec2d2..2c22f99a0ab4da56623f6f15542b703035c736d3 100644 (file)
@@ -101,7 +101,17 @@ struct LiteralPool;
 
 
 /* Symbol table entry */
+
+typedef struct DefOrRef DefOrRef;
+
+struct DefOrRef {
+    unsigned            Line;
+    long                LocalsBlockNum;
+    unsigned            Flags;
+};
+
 typedef struct SymEntry SymEntry;
+
 struct SymEntry {
     SymEntry*                   NextHash; /* Next entry in hash list */
     SymEntry*                   PrevSym;  /* Previous symbol in dl list */
@@ -120,7 +130,10 @@ struct SymEntry {
         int                     Offs;
 
         /* Label name for static symbols */
-        unsigned                Label;
+        struct {
+            unsigned            Label;
+            Collection          *DefsOrRefs;
+        } L;
 
         /* Register bank offset and offset of the saved copy on stack for
         ** register variables.
index 3275332c5490c68b89ab7a5c4b6e560716574144..51b43b4c91a7c04df2f3e52f560522353ca82873 100644 (file)
@@ -57,6 +57,8 @@
 #include "symentry.h"
 #include "typecmp.h"
 #include "symtab.h"
+#include "function.h"
+#include "input.h"
 
 
 
@@ -658,10 +660,26 @@ SymEntry* AddConstSym (const char* Name, const Type* T, unsigned Flags, long Val
 }
 
 
+DefOrRef* AddDefOrRef(SymEntry* E, unsigned Flags)
+/* Add definition or reference to the SymEntry and preserve its attributes */
+{
+    DefOrRef *DOR;
+
+    DOR = xmalloc (sizeof (DefOrRef));
+    CollAppend (E->V.L.DefsOrRefs, DOR);
+    DOR->Line = GetCurrentLine ();
+    DOR->LocalsBlockNum = (long)CollLast (&CurrentFunc->LocalsBlockStack);
+    DOR->Flags = Flags;
+
+    return DOR;
+}
+
 
 SymEntry* AddLabelSym (const char* Name, unsigned Flags)
 /* Add a goto label to the label table */
 {
+    unsigned i;
+    DefOrRef *DOR;
     /* Do we have an entry with this name already? */
     SymEntry* Entry = FindSymInTable (LabelTab, Name, HashStr (Name));
     if (Entry) {
@@ -670,6 +688,24 @@ SymEntry* AddLabelSym (const char* Name, unsigned Flags)
             /* Trying to define the label more than once */
             Error ("Label `%s' is defined more than once", Name);
         }
+
+        /* Walk through all occurrences of the label so far and check
+           if any of them is in a region that would be risky to jump from/to
+           from the place where we are right now. */
+        for (i = 0; i < CollCount (Entry->V.L.DefsOrRefs); i++) {
+            DOR = CollAt (Entry->V.L.DefsOrRefs, i);
+            /* We are only interested in label occurences of type opposite to
+             the one currently being added, i.e.  if we are processing the
+             definition, we will only check the gotos; if we are processing
+             a goto statement, we will only look for the label definition. */
+            if (((DOR->Flags & SC_DEF) != (Flags & SC_DEF)) &&
+                (DOR->LocalsBlockNum != (long)CollLast (&CurrentFunc->LocalsBlockStack)))
+                Warning ("Goto from line %d to label \'%s\' can result in a "
+                    "trashed stack", Flags & SC_DEF ? DOR->Line : GetCurrentLine (), Name);
+        }
+
+        AddDefOrRef (Entry, Flags);
+
         Entry->Flags |= Flags;
 
     } else {
@@ -678,10 +714,14 @@ SymEntry* AddLabelSym (const char* Name, unsigned Flags)
         Entry = NewSymEntry (Name, SC_LABEL | Flags);
 
         /* Set a new label number */
-        Entry->V.Label = GetLocalLabel ();
+        Entry->V.L.Label = GetLocalLabel ();
+
+        /* Create Collection for label definition and references */
+        Entry->V.L.DefsOrRefs = NewCollection ();
+        AddDefOrRef (Entry, Flags);
 
         /* Generate the assembler name of the label */
-        Entry->AsmName = xstrdup (LocalLabelName (Entry->V.Label));
+        Entry->AsmName = xstrdup (LocalLabelName (Entry->V.L.Label));
 
         /* Add the entry to the label table */
         AddSymEntry (LabelTab, Entry);
@@ -717,12 +757,12 @@ SymEntry* AddLocalSym (const char* Name, const Type* T, unsigned Flags, int Offs
             Entry->V.R.RegOffs  = Offs;
             Entry->V.R.SaveOffs = StackPtr;
         } else if ((Flags & SC_EXTERN) == SC_EXTERN) {
-            Entry->V.Label = Offs;
+            Entry->V.L.Label = Offs;
             SymSetAsmName (Entry);
         } else if ((Flags & SC_STATIC) == SC_STATIC) {
             /* Generate the assembler name from the label number */
-            Entry->V.Label = Offs;
-            Entry->AsmName = xstrdup (LocalLabelName (Entry->V.Label));
+            Entry->V.L.Label = Offs;
+            Entry->AsmName = xstrdup (LocalLabelName (Entry->V.L.Label));
         } else if ((Flags & SC_STRUCTFIELD) == SC_STRUCTFIELD) {
             Entry->V.Offs = Offs;
         } else {