[Python-Dev] test_sre.py fails on Win64 because PyOS_CheckStack *never* fails

Trent Mick trentm@ActiveState.com
Mon, 9 Oct 2000 15:56:00 -0700


[Trent notes that PyOS_CheckStack never fails on Win64 hence test_[s]re.py
    fail on the overflow checks]

[Fredrik gives me a simple test C program to test PyOS_CHeckStack
    independently (The test program is included at the bottom of this
    email.)]

SOrry I took so long to reply to this but I spent a little bit of time
playing with PyOS_CheckStack on Win32 and Win64 and I am now just frustrated.
Here is what I found:

- The simple test program shows that PyOS_CheckStack will fire as intended
  on both Win32 and Win64 with either Visual C's default optimization OR no
  optimization.
- The simple test program will *not* fire as intended with the '-O2'
  optimization which Python *does* use for pythonrun.c (where
  PyOS_CheckStack lives). So, likely the '-O2' optimization will
  optimize-away the _alloca() call. Fine. But why then does it *not* get
  optimized away when pythonrun.c is compiled? Does the context around other
  code in the same file affect that optimization?
- When I apply this patch to _sre.c on *Win32* (basically the same test as
  the test file that Fredrik gave me to try) the "callme(0)" call *never*
  returns -- infinite loop. Note that this happens on the Release *and* Debug
  builds so nothing is being optimized away.

***************
*** 560,565 ****
--- 560,569 ----
  }
  #endif

+
+
+ void callme(int i);
+
  LOCAL(int)
  SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern, int level)
  {
***************
*** 578,583 ****
--- 582,588 ----
      TRACE(("|%p|%p|ENTER %d\n", pattern, ptr, level));

  #if defined(USE_STACKCHECK)
+     callme(0);
      if (level % 10 == 0 && PyOS_CheckStack())
          return SRE_ERROR_RECURSION_LIMIT;
  #endif
***************
*** 2337,2340 ****
--- 2342,2357 ----
      Py_InitModule("_" MODULE, _functions);
  }

+ void callme(int i)
+ {
+     char buf[100000];
+     if (PyOS_CheckStack())
+         return;
+     printf("%d\n", i);
+     memset(buf, 0, sizeof buf);
+     callme(i+1);
+ }
+
+
+
  #endif /* !defined(SRE_RECURSIVE) */

- I am not smart enough and/or (you decide :) do not have the inclination to
  figure this out (i.e. start looking at assembly code) just so _sre can use
  stack checking instead of the existing RECURSION_LIMIT framework (albeit
  the limited general usefullness of this) on Win64 so that test_sre.py can
  pass.

  Would it be alright for me to apply:


*** python/dist/src/Include/pythonrun.h       Sat Sep 16 09:31:31 2000
--- python/dist/src/Include/pythonrun.h  Sun Oct  8 10:20:02 2000
***************
*** 88,94 ****
     to a 8k margin. */
  #define PYOS_STACK_MARGIN 2048

! #if defined(WIN32) && defined(_MSC_VER)
  /* Enable stack checking under Microsoft C */
  #define USE_STACKCHECK
  #endif
--- 88,94 ----
     to a 8k margin. */
  #define PYOS_STACK_MARGIN 2048

! #if defined(WIN32) && !defined(MS_WIN64) && defined(_MSC_VER)
  /* Enable stack checking under Microsoft C */
  #define USE_STACKCHECK
  #endif


  to disable stack checking on Win64 until Win64 become more mainstream and
  others can bang away at this? The important thing, I would think, is
  getting the test suite passing for Python 2.0.


------- test file mentioned above --------------------------------
#include <malloc.h>
#include <excpt.h>

int __inline
PyOS_CheckStack()
{
    __try {
        _alloca(100000);
        return 0;
    } __except (EXCEPTION_EXECUTE_HANDLER) {
        /* just ignore all errors */
    }
    return 1;
}

void
callme(int i)
{
    char buf[100000];
    if (PyOS_CheckStack())
        return;
    printf("%d\n", i);
    memset(buf, 0, sizeof buf);
    callme(i+1);
}

int
main()
{
    callme(0);
}
-----------------------------------------------------


-- 
Trent Mick
TrentM@ActiveState.com