From: anton@mips.complang.tuwien.ac.at   
      
   Krishna Myneni writes:   
   >On 3/2/24 10:43, Anton Ertl wrote:   
   >> With the gforth engine with the FP stack being empty:   
   >>   
   >> fp@ 32769 - c@   
   >> *the terminal*:3:13: error: Floating-point stack overflow   
   >> fp@ 32769 - >>>c@<<<   
   >> fp@ 1+ c@   
   >> *the terminal*:4:8: error: Floating-point stack underflow   
   >> fp@ 1+ >>>c@<<<   
   >>   
   >   
   >In the version of Gforth which I have (0.7.9_20220120),   
   >   
   >fp@ 32769 - c@   
   >*the terminal*:5:13: error: Floating-point stack overflow   
   >fp@ 32769 - >>>c@<<<   
   >   
   >However,   
   >   
   >fp@ 65536 - c@ ok 1   
   >   
   >and, worse,   
   >   
   >1 fp@ 65536 - c! ok   
   >   
   >So the guard pages are not a solution to pointer arithmetic bugs with   
   >the stack pointers.   
      
   Yes, that is not their intention and not the intention of these   
   examples. The intention of these examples is to show that any memory   
   access will be interpreted as a stack underflow or overflow if it is   
   to a certain range of addresses.   
      
   A more serious issue is that, as implemented in Gforth (in particular,   
   gforth-fast), stack underflows can be undetected in some cases: On   
   Gforth on an AMD64 system, with the data stack being empty:   
      
   600 pick ok 1   
      
   On gforth-fast, with the data stack being empty:   
      
   : foo 600 0 ?do nip loop cr . ; foo   
   0   
   *the terminal*:1:33: error: Stack underflow   
   : foo 600 0 ?do nip loop cr . ; >>>foo<<<   
   Backtrace:   
   kernel/basics.fs:312:27: 0 $7F30E3BDFE10 throw   
      
   Note that FOO actually performs the "cr .", so the stack underflow is   
   not detected by an access to the the guard page. Instead, the text   
   interpreter checks the stack pointer and reports a stack underflow.   
   The non-detection of the stack underflow is because NIP is implemented   
   as:   
      
   $7F30E3C72C90 nip 1->1   
   7F30E3917557: add r13,$08 #update sp   
      
   With the gforth engine, a similar scenario (involving DROP) is avoided   
   because in this engine DROP loads the value being dropped exactly to   
   trigger stack underflow reports where they happen:   
      
   $7F55EBFA6C98 drop 0->0   
   7F55EBAC51C0: mov $50[r13],r15 #save ip (for accurate backtraces)   
   7F55EBAC51C4: add r15,$08 #update ip   
   7F55EBAC51C8: mov rax,[r14] #load dropped value   
   7F55EBAC51CB: add r14,$08 #update sp   
      
   Neither the deep PICK nor the loop that just NIPs or DROPs occur in   
   practice.   
      
   The motivation for the otherwise unnecessary load in DROP (in gforth)   
   is code sequences like   
      
   drop 1   
      
   in cases where the stack is empty. The load in DROP results in   
   detecting the stack underflow at the DROP rather than at the "1".   
   Reporting a stack underflow at an operation that just pushes can   
   produce a WTF moment in the programmer; the gforth engine exists to   
   make debugging easier, and that includes avoiding such moments.   
      
   >To make stack access memory safe, there has to be bounds checks on   
   >reading and writing from/to stacks. This suggests that stacks should be   
   >arrays and stack operations always involve array read/write from arrays   
   >with enforced bounds checking e.g. something like   
   >   
   >: DUP STACK[ tos ]@ ; \ TOS returns an index to the top of the stack   
   >: OVER STACK[ tos 1+ ]@ ;   
   >   
   >etc. and ]@ and ]! performs bounds checks.   
      
   With guard pages, that's not necessary. The normal bounded-depth   
   stack accesses (of words like 2DROP or 2OVER) are sure to hit the   
   guard pages if the stack is out-of-bounds; you may want to perform an   
   otherwise unnecessary load on words like NIP, DROP, 2DROP etc. that do   
   not otherwise use (and thus load) the stack values that they consume,   
   but that's much cheaper than putting bounds checks on every stack   
   access. For unbounded stack-access words like PICK, a bounds check is   
   appropriate.   
      
   - anton   
   --   
   M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html   
   comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html   
    New standard: https://forth-standard.org/   
    EuroForth 2023: https://euro.theforth.net/2023   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   
|