From:	CSBVAX::CSBVAX::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX" 20-MAR-1989 17:31
To:	MRGATE::"ARISIA::EVERHART"
Subj:	stack overflow.


Received: From KL.SRI.COM by CRVAX.SRI.COM with TCP; Mon, 20 MAR 89 13:30:33 PDT
Received: from bu-it.BU.EDU by KL.SRI.COM with TCP; Mon, 20 Mar 89 13:04:03 PST
Received: by bu-it.BU.EDU (5.58/4.7)
	id AA03459; Mon, 20 Mar 89 16:00:29 EST
Date: Mon, 20 Mar 89 16:00:29 EST
From: gjc@bu-it.BU.EDU (George J. Carrette)
Message-Id: <8903202100.AA03459@bu-it.BU.EDU>
To: info-vax@kl.sri.com
Subject: stack overflow.

If you have a program you are debugging which is prone to indefinite
recursion, and you hate to wait for your program to run out of
page file quota, (or worse, system page file as in a previous problem
with VMS fortran) then the techniques illustrated in this example
may be of help.

This program first recurses a certain amount X, as specified by the
first argument. It then protects pages in the "stack area" which are
beyond the space already in use against further use. It then
recurses an amount Y, as specified by the second argument.
If Y is greater than X by at least a page (depending on page boundaries)
then the program will exit instead of using up your page file quota.

* If anyone wants to improve on this program with a good exception handler
  then please do!

/* Illustrate the setting of page protection on
   virtual memory at the end of the program stack.
   20-MAR-89 George Carrette, Mitech Corporation.

   This prevents a program from recursing much more
   than a certain amount. A priviledged exception
   handler should be established if you want to prevent
   an image exit due to "Improperly Handled Condition"

$stackp 1000 1000
 will work ok.

$stackp X Y
 will always work if X is greater than or equal to Y.

$stackp 1000 1100
 will probably blow up.

$stackp 1000 1001
 will probably work, but may blow up, depending on stack page
 alignment factors.


   
 */


#include <stdio.h>

#include <ssdef.h>

/* test stack protection */

globalvalue JPI$_FREP1VA;

err_exit(x)
     int x;
{exit(x);}

jpi_frep1va()
{int retval,value,code;
 code = JPI$_FREP1VA;
 retval = lib$getjpi(&code,0,0,&value,0,0);
 if (retval != SS$_NORMAL) err_exit(retval);
 return(value);}

globalvalue PRT$C_NA;
globalvalue PRT$C_KR;
globalvalue PRT$C_KW;
globalvalue PRT$C_ER;
globalvalue PRT$C_EW;
globalvalue PRT$C_SR;
globalvalue PRT$C_SW;
globalvalue PRT$C_UR;
globalvalue PRT$C_UW;
globalvalue PRT$C_ERKW;
globalvalue PRT$C_SRKW;
globalvalue PRT$C_SREW;
globalvalue PRT$C_URKW;
globalvalue PRT$C_UREW;
globalvalue PRT$C_URSW;


char *decode_prot(x)
     int x;
{if (x == PRT$C_NA) return("PRT$C_NA");
 if (x == PRT$C_KR) return("PRT$C_KR");
 if (x == PRT$C_KW) return("PRT$C_KW");
 if (x == PRT$C_ER) return("PRT$C_ER");
 if (x == PRT$C_EW) return("PRT$C_EW");
 if (x == PRT$C_SR) return("PRT$C_SR");
 if (x == PRT$C_SW) return("PRT$C_SW");
 if (x == PRT$C_UR) return("PRT$C_UR");
 if (x == PRT$C_UW) return("PRT$C_UW");
 if (x == PRT$C_ERKW) return("PRT$C_ERKW");
 if (x == PRT$C_SRKW) return("PRT$C_SRKW");
 if (x == PRT$C_SREW) return("PRT$C_SREW");
 if (x == PRT$C_URKW) return("PRT$C_URKW");
 if (x == PRT$C_UREW) return("PRT$C_UREW");
 if (x == PRT$C_URSW) return("PRT$C_URSW");
 return("unknown");}


main(argc,argv)
     int argc; char **argv;
{int try1,try2,prot,p1;
 if (argc > 1) try1 = atol(argv[1]); else try1 = 100;
 if (argc > 2) try2 = atol(argv[2]); else try2 = 100;
 if (argc > 3) prot = atol(argv[3]); else prot = PRT$C_URSW;
 printf("FREP1VA now 0x%8X\n",jpi_frep1va());
 printf("recursing to depth %d\n",try1);
 recurse_some(try1);
 p1 = jpi_frep1va();
 printf("FREP1VA now 0x%8X\n",p1);
 printf("Adding another page of memory\n");
 add_p1_page();
 printf("FREP1VA now 0x%8X\n",jpi_frep1va());
 printf("Setting protection of page\n");
 set_prot(p1,prot);
 printf("Now recursing to depth %d\n",try2);
 recurse_some(try2);}


add_p1_page()
{int retval;
 long added[2];
 retval = sys$expreg(1,&added,0,1);
 if (retval != SS$_NORMAL) err_exit(retval);
 printf("Pages added to P1 region [0x%8X, 0x%8X]\n",added[0],added[1]);}


set_prot(paddr,new)
     int paddr,new;
{long rpgs[2],spgs[2];
 int retval;
 unsigned char oprot;
 rpgs[0] = paddr;
 rpgs[1] = paddr;
 retval = sys$setprt(&rpgs,&spgs,0,new,&oprot);
 if (retval != SS$_NORMAL) err_exit(retval);
 printf("Changed protection of [0x%8X,0x%8X] (0x%8X,0x%8X)\n",
	rpgs[0],rpgs[1],spgs[0],spgs[1]);
 printf("From %d (%s) to %d (%s)\n",
	oprot,decode_prot(oprot),
	new,decode_prot(new));}

recurse_some(x)
     int x;
{if (x == 0) return;
 recurse_some(x-1);}

