home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / Demos / Tools / QC™ 1.1.3 / QCAPI / BadAPPL / BadAPPL src / BadErrors.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-21  |  18.1 KB  |  603 lines  |  [TEXT/R*ch]

  1. /*________________________________________________________________________________
  2.  
  3.     BadErrors.c
  4.  
  5.     Copyright © 1993-1995 Onyx Technology - All rights reserved
  6.  
  7.     This file contains the routines that performs the errors for BadAPPL.
  8.  
  9.     There is use of a routine called ‘OutputString’ in every routine.  This routine simply
  10.     outputs string resources to the status window during each test.  If you are trying to
  11.     follow what the code is doing, you can ignore calls to this routine.
  12.  
  13.     Also note that heavy use of the QC API is done in this file.  Each routine makes
  14.     sure that the QC test it will be testing is active by setting the threshold to the
  15.     activation level of that test.  This is done with code similar to:
  16.  
  17.         saveStateH = QCGetState();                        // save the current testing state
  18.         QCSetTestState(qcValidateHandlePointers, true);    // make sure validate handle/ptrs is on
  19.  
  20.      If you are not familiar with the API routines, please refer to ‘Section 5 - Inside QC’
  21.      of the QC User Manual.
  22.     
  23.     Like all other files related to BadAPPL, intentional errors are marked like:
  24.         // •-> BAD - This is an intentional error
  25.     
  26. ________________________________________________________________________________*/
  27.  
  28. #ifndef    _H_BadAPPL
  29. #include "BadAPPL.h"
  30. #endif
  31. #ifndef    _H_BadWindows
  32. #include "BadWindows.h"
  33. #endif
  34. #ifndef    _H_BadUtils
  35. #include "BadUtils.h"
  36. #endif
  37. #ifndef    _H_BadMacros
  38. #include "BadMacros.h"
  39. #endif
  40. #ifndef    _H_BadErrors
  41. #include    "BadErrors.h"
  42. #endif
  43. #ifndef    _H_BadGlobs
  44. #include "BadGlobs.h"
  45. #endif
  46. #ifndef    _H_QCAPI
  47. #include "QCAPI.h"
  48. #endif
  49.  
  50. static    short    gQCDetectedErr;
  51.  
  52. // QC error handler installation routines
  53.         Boolean            MyErrorHandler(QCPBPtr paramBlock);
  54.  
  55. /*________________________________________________________________________________
  56.  
  57.     DoHandleExistance()
  58.  
  59.     info:     This routine performs the create/dispose test on Handles or Pointers
  60.             depending on the value passed in onHandle.
  61.  
  62.     entry:    onHandle    - true if we are testing Handles, false if we are testing Pointers
  63.  
  64. ________________________________________________________________________________*/
  65. void    DoHandlePtrExistance(Boolean onHandle)
  66. {
  67.     QCStateHandle    saveStateH;
  68.     Handle            testHnd        = 0L;
  69.     Ptr                testPtr        = 0L;
  70.     short            stringsID;
  71.  
  72.     if (onHandle)
  73.         stringsID    =    kHndStringsID;                // we are performing a handle test
  74.     else
  75.         stringsID    =    kPtrStringsID;                // we are performing a Ptr test
  76.  
  77.     saveStateH = QCGetState();                        // save the current testing state
  78.     QCSetTestState(qcValidateHandlePointers, true);    // make sure validate handle/ptrs is on
  79.     gQCDetectedErr = kQCNoErr;
  80.  
  81.     OutputString( stringsID, kHndPtr1, 0L);
  82.  
  83.     if (onHandle)                                    // are we testing Handles or Pointers?
  84.         testHnd        =    NewHandle(12800);            // create a handle
  85.     else
  86.         testPtr        =    NewPtr(12800);                // create a pointer
  87.  
  88.     if ((onHandle && (!testHnd)) || (!onHandle && (!testPtr)))                        
  89.         OutputString(stringsID, kHndPtr2, 0L);
  90.     else
  91.         {
  92.         if (onHandle)                                // are we testing Handles or Pointers?
  93.             OutputString(stringsID, kHndPtr3, (long) *testHnd);
  94.         else
  95.             OutputString(stringsID, kHndPtr3, (long) testPtr);
  96.         
  97.         if (onHandle)                                // are we testing Handles or Pointers?
  98.             DisposHandle(testHnd);                    // this is okay, disposing the Handle here
  99.         else
  100.             DisposPtr(testPtr);                        // this is okay, disposing the Ptr here
  101.  
  102.         OutputString(stringsID, kHndPtr4, 0L);
  103.  
  104.         OutputString(stringsID, kHndPtr5, 0L);
  105.  
  106.         if (onHandle)                                // are we testing Handles or Pointers?
  107.             DisposHandle(testHnd);                    //•-> BAD - the Handle is already disposed!
  108.         else
  109.             DisposPtr(testPtr);                        //•-> BAD - the Ptr is already disposed!
  110.         
  111.         DetectedMsgs();
  112.         }
  113.     
  114.     OutputString( stringsID, kHndPtr6, 0L);
  115.  
  116.     if (saveStateH)
  117.         {
  118.         QCSetState(saveStateH);                        // if successful, we don't dispose of it
  119.         QCDisposeState(saveStateH);
  120.         }
  121. }
  122.  
  123.  
  124.  
  125. /*________________________________________________________________________________
  126.  
  127.     DoHandlePtrResize()
  128.  
  129.     info:     This routine performs the resize tests on Handles or Pointers
  130.             depending on the value passed in onHandle.
  131.  
  132.     entry:    onHandle    - true if we are testing Handles, false if we are testing Pointers
  133.  
  134. ________________________________________________________________________________*/
  135. void    DoHandlePtrResize(Boolean onHandle)
  136. {
  137.     QCStateHandle    saveStateH;
  138.     Handle            testHnd        = 0L;
  139.     Ptr                testPtr        = 0L;
  140.     short            stringsID;
  141.  
  142.     if (onHandle)
  143.         stringsID    =    kHndStringsID;                // we are performing a handle test
  144.     else
  145.         stringsID    =    kPtrStringsID;                // we are performing a Ptr test
  146.  
  147.     saveStateH = QCGetState();                        // save the current testing state
  148.     QCSetTestState(qcValidateHandlePointers, true);    // make sure validate handle/ptrs is on
  149.     gQCDetectedErr = kQCNoErr;
  150.  
  151.     OutputString( stringsID, kHndPtr11, 0L);
  152.  
  153.     if (onHandle)                                    // are we testing Handles or Pointers?
  154.         testHnd        =    NewHandle(128);                // create a handle
  155.     else
  156.         testPtr        =    NewPtr(128);                // create a pointer
  157.  
  158.     if ((onHandle && (!testHnd)) || (!onHandle && (!testPtr)))                        
  159.         OutputString(stringsID, kHndPtr12, 0L);
  160.     else
  161.         {
  162.         if (onHandle)                                // are we testing Handles or Pointers?
  163.             OutputString(stringsID, kHndPtr13, (long) *testHnd);
  164.         else
  165.             OutputString(stringsID, kHndPtr13, (long) testPtr);
  166.  
  167.         OutputString(stringsID, kHndPtr14, 0L);
  168.         
  169.         if (onHandle)                                // are we testing Handles or Pointers?
  170.             DisposHandle(testHnd);                    // this is okay, disposing the Handle here
  171.         else
  172.             {
  173.             DisposPtr(testPtr);                        // this is okay, disposing the Ptr here
  174.             }
  175.  
  176.         OutputString(stringsID, kHndPtr15, 0L);
  177.  
  178.         if (onHandle)                                // are we testing Handles or Pointers?
  179.             SetHandleSize(testHnd, 256);            //•-> BAD - the Handle is already disposed!
  180.         else
  181.             {
  182.             // Important note!
  183.             // A call to resize a disposed pointer can result in a out of memory error!
  184.             // QC will detect this call, but because program execution continues, the
  185.             // app may crash with a SysErr 25 in the SetPtrSize call.
  186.  
  187.             SetPtrSize(testPtr, 256);                //•-> BAD - the Ptr is already disposed!
  188.             }
  189.         }
  190.     
  191.     DetectedMsgs();
  192.     OutputString( stringsID, kHndPtr16, 0L);
  193.  
  194.     if (saveStateH)
  195.         {
  196.         QCSetState(saveStateH);                        // if successful, we don't dispose of it
  197.         QCDisposeState(saveStateH);
  198.         }
  199. }
  200.  
  201. /*________________________________________________________________________________
  202.  
  203.     DoHandlePtrVerify()
  204.  
  205.     info:     This routine performs a handle or pointer verification using
  206.             the API calls QCVerifyHandle or QCVerifyPtr
  207.  
  208.     entry:    onHandle    - true if we are testing Handles, false if we are testing Pointers
  209.  
  210. ________________________________________________________________________________*/
  211. void    DoHandlePtrVerify(Boolean onHandle)
  212. {
  213.     long            value;                                // blocks with.
  214.  
  215.     if (onHandle)
  216.         OutputString( kVerifyStringsID, kVerify2, 0L);
  217.     else
  218.         OutputString( kVerifyStringsID, kVerify1, 0L);
  219.  
  220.     QCGetTestState(qcDebugBreaks, &value);                // are debug breaks turned on?
  221.     if (!value)
  222.         OutputString(kVerifyStringsID, kVerify11, 0L);
  223.  
  224.     if (QCIsActive())
  225.         {
  226.         QCStateHandle    saveStateH;
  227.         Handle            testHnd        = (Handle) 0x52FF8001;    // Some bogus values: these are the
  228.         Ptr                testPtr        = (Ptr) 0x52FF8001;        // values QC invalidates free memory
  229.  
  230.         saveStateH = QCGetState();                        // save the current testing state
  231.         QCSetTestState(qcValidateHandlePointers, true);    // make sure validate handle/ptrs is on
  232.         gQCDetectedErr = kQCNoErr;
  233.  
  234.         if (onHandle)                                    // are we testing Handles or Pointers?
  235.             {
  236.             OutputString(kVerifyStringsID, kVerify5, 0L);
  237.             if (QCVerifyHandle(testHnd))
  238.                 OutputString(kVerifyStringsID, kVerify9, 0L);
  239.             else
  240.                 OutputString(kVerifyStringsID, kVerify8, 0L);
  241.             }
  242.         else
  243.             {
  244.             OutputString(kVerifyStringsID, kVerify4, 0L);
  245.             if (QCVerifyPtr(testPtr))
  246.                 OutputString(kVerifyStringsID, kVerify7, 0L);
  247.             else
  248.                 OutputString(kVerifyStringsID, kVerify6, 0L);
  249.             }
  250.  
  251.         if (saveStateH)
  252.             {
  253.             QCSetState(saveStateH);                        // if successful, we don't dispose of it
  254.             QCDisposeState(saveStateH);
  255.             }
  256.         }
  257.     else
  258.         OutputString(kVerifyStringsID, kVerify10, 0L);
  259.  
  260.     DetectedMsgs();
  261.  
  262.     OutputString( kVerifyStringsID, kVerify12, 0L);
  263. }
  264.  
  265.  
  266. /*________________________________________________________________________________
  267.     WriteToZeroTest()
  268.  
  269.     info:     This routine does the write to zero test by performing a common error
  270.             in use of the Dialog Manager.  This routine executes a GetDItem call
  271.             by passing 0L in the VAR Handle parameter specified in Inside Mac I.
  272.             The Dialog Manager writes the handle to the dialog item (in this case a
  273.             button) in the expected VAR handle passed in.  Because 0L was passed in,
  274.             the Dialog Manager writes the button handle to address zero instead.
  275.  
  276. ________________________________________________________________________________*/
  277. void    WriteToZeroTest(void)
  278. {
  279.     DialogPtr        my_dialog;
  280.     Point            dlgOrigin;
  281.  
  282.     if (!gAtleastSys7)                                // if we are pre 7.0, we need to
  283.         CenterDialog('DLOG', badDLOG, &dlgOrigin);    // center it ourselves
  284.  
  285.     if ((my_dialog = GetNewDialog(badDLOG, 0, (WindowPtr)-1L))) // intentional assignment
  286.         {
  287.         QCStateHandle    savedStateH;
  288.         GrafPtr            savePort;
  289.         Rect             boxT;
  290.         short            type, item_hit = 0;
  291.  
  292.         ShowWindow(my_dialog);                        // because we have it initially
  293.                                                     // inivisible in the DLOG tmpl
  294.         GetPort( &savePort);
  295.         SetPort(my_dialog);
  296.  
  297.         if (QCIsActive())
  298.             {
  299.             savedStateH = QCGetState();                // save the current state
  300.             QCSetTestState(qcDetectWriteToZero, true);    // ensure this is on
  301.             }
  302.  
  303.         GetDItem(my_dialog, iOkay, &type, 0L, &boxT); //•-->BAD should pass &temp_H not 0L
  304.         FrameDefault( &boxT);
  305.  
  306.         ModalDialog(0L, &item_hit);
  307.  
  308.         DisposDialog(my_dialog);
  309.  
  310.         if (savedStateH)
  311.             {
  312.             if (savedStateH)
  313.                 {
  314.                 QCSetState(savedStateH);            // if successful, we don't dispose of it
  315.                 QCDisposeState(savedStateH);
  316.                 }
  317.             }
  318.  
  319.         SetPort(savePort);
  320.         }
  321. }
  322.  
  323.  
  324. /*________________________________________________________________________________
  325.  
  326.     DerefZeroTest()
  327.  
  328.     info:     This routine performs the Dereferencing Zero Test.  This test is performed
  329.             by creating a purgeable handle, making sure it is purged through the
  330.             use of QC’s purge memory option, then attempting to the use the
  331.             purged handle.
  332.  
  333.             Note that this routine is almost identical to DoPurgeTest with the exception
  334.             that we attempt to use the purged handle here.
  335.  
  336. ________________________________________________________________________________*/
  337. void    DerefZeroTest(void)
  338. {
  339.     QCStateHandle    saveStateH;
  340.     dummyDataH        testHandle1    = 0L;
  341.     Handle            testHandle2    = 0L;
  342.     Ptr                testPtr1    = 0L;
  343.     Ptr                testPtr;                        // this is what we use to cause the err
  344.     long            testLong;                        // this is what we use to cause the err
  345.  
  346.     saveStateH = QCGetState();
  347.     QCSetTestState(qcPurgeHeap, true);                // make sure this is turned on
  348.     QCSetTestState(qcDerefZeroCheck, true);            // make sure this is turned on
  349.  
  350.     OutputString( kZeroStringsID, kZero1, 0L);        // report the first indicator string
  351.  
  352.     testHandle1    =    (dummyDataH) NewHandle(1024);    // lets create a handle
  353.  
  354.     if (testHandle1)                                // did we get the handle?
  355.         {
  356.         OutputString( kZeroStringsID, kZero3, (long) testHandle1); // show the handle address
  357.  
  358.         OutputString( kZeroStringsID, kZero4, 0L);
  359.  
  360.         if (QCIsActive())
  361.             OutputString( kZeroStringsID, kZero5, 0L);
  362.         else
  363.             OutputString( kZeroStringsID, kZero6, 0L);
  364.  
  365.         HPurge((Handle) testHandle1);                // mark him purgeable
  366.         testHandle2    =    NewHandle(1024);            // and create another 1k handle
  367.  
  368.         if (!*testHandle1)                            // have we been purged?
  369.             OutputString( kZeroStringsID, kZero7, 0L);
  370.         else
  371.             OutputString( kZeroStringsID, kZero8, 0L);
  372.  
  373.         if (testHandle1)                            // it is still a handle in memory even
  374.             {                                        // though its contents have been purged
  375.             OutputString( kZeroStringsID, kZero9, 0L);
  376.  
  377.             if (QCIsActive())                        // is QC active?
  378.                 OutputString( kZeroStringsID, kZero10, 0L);
  379.             else
  380.                 OutputString( kZeroStringsID, kZero11, 0L);
  381.  
  382.             testPtr = (**testHandle1).theData;        // •-> BAD the handle was purged!!
  383.                                                     // this is now invalid data from addr Zero.
  384.             testLong = (long) *testPtr;                // now we try to pull some data out of this
  385.                                                     // purged handle.
  386.             DisposHandle((Handle) testHandle1);
  387.             }
  388.             
  389.         if (testHandle2)                            // get rid of the trouble maker
  390.             DisposHandle(testHandle2);
  391.  
  392.         }
  393.     else
  394.         OutputString( kZeroStringsID, kZero2, 0L);
  395.  
  396.     DetectedMsgs();
  397.     OutputString( kZeroStringsID, kZero12, 0L);
  398.  
  399.     if (saveStateH)
  400.         {
  401.         QCSetState(saveStateH);                        // if successful, we don't dispose of it
  402.         QCDisposeState(saveStateH);
  403.         }
  404. }
  405.  
  406.  
  407. /*________________________________________________________________________________
  408.  
  409.     DoPurgeTest()
  410.  
  411.     info:     This routine performs the purge memory test.  The test involves reading
  412.             in a given resource, marking it as purgeable, then causing memory to be
  413.             purged by creating a big Handle, then trying to access the resource again.
  414.  
  415. ________________________________________________________________________________*/
  416. void    DoPurgeTest(void)
  417. {
  418.     QCStateHandle    saveStateH;
  419.     Handle            testHandle1    = 0L;
  420.     Handle            testHandle2    = 0L;
  421.  
  422.     saveStateH = QCGetState();                        // save the current testing state
  423.     QCSetTestState(qcPurgeHeap, true);                // make sure this is turned on
  424.     QCSetTestState(qcScrambleHeap, true);            // make sure this is turned on
  425.     gQCDetectedErr = kQCNoErr;
  426.  
  427.     OutputString( kPurgeStringsID, kPurge1, 0L);    // report the first indicator string
  428.  
  429.     testHandle1    =    NewHandle(1024);                // lets create a handle
  430.  
  431.     if (testHandle1)                                // did we get the handle?
  432.         {
  433.         OutputString( kPurgeStringsID, kPurge3, (long) testHandle1); // show the handle address
  434.  
  435.         OutputString( kPurgeStringsID, kPurge4, 0L);
  436.  
  437.         if (QCIsActive())
  438.             OutputString( kPurgeStringsID, kPurge5, 0L);
  439.         else
  440.             OutputString( kPurgeStringsID, kPurge6, 0L);
  441.  
  442.         HPurge(testHandle1);                        // mark him purgeable
  443.         testHandle2    =    NewHandle(1024);            // and create another 1k handle
  444.  
  445.         if (!*testHandle1)                            // have we been purged?
  446.             OutputString( kPurgeStringsID, kPurge7, 0L);
  447.         else
  448.             OutputString( kPurgeStringsID, kPurge8, 0L);
  449.  
  450.         if (testHandle1)                            // it is still a handle in memory even
  451.             DisposHandle(testHandle1);                // though its contents have been purged
  452.             
  453.         if (testHandle2)                            // get rid of the trouble maker
  454.             DisposHandle(testHandle2);
  455.  
  456.         }
  457.     else
  458.         OutputString( kPurgeStringsID, kPurge2, 0L);
  459.  
  460.     DetectedMsgs();
  461.     OutputString( kPurgeStringsID, kPurge9, 0L);
  462.  
  463.     if (saveStateH)
  464.         {
  465.         QCSetState(saveStateH);                        // if successful, we don't dispose of it
  466.         QCDisposeState(saveStateH);
  467.         }
  468. }
  469.  
  470.  
  471. #define    kArrayMax        9
  472. /*________________________________________________________________________________
  473.  
  474.     DoBlockOverwrite()
  475.  
  476.     info:     This routine performs a block overwrite off data in a handle by
  477.             creating a handle of longs and incorrectly looping one past the end
  478.             of the array.  Please notice that the error is detected on the next
  479.             memory related call (the _DisposeHandle).
  480. ________________________________________________________________________________*/
  481. void    DoBlockOverwrite(void)
  482. {
  483.     QCStateHandle    saveStateH;
  484.     shortHandle        testH;
  485.     Handle            spareH;
  486.     short            loop;
  487.     Boolean            active = QCIsActive();
  488.  
  489.     gQCDetectedErr = kQCNoErr;
  490.  
  491.     OutputString( kBkOverwriteStringsID, kOverwrite1, 0L);    // report the first indicator string
  492.  
  493.     saveStateH = QCGetState();                                // save the current testing state
  494.     QCSetTestState(qcBlockBoundsChecking, true);            // make sure block bounds is on
  495.  
  496.     if (!active)
  497.         OutputString( kBkOverwriteStringsID, kPurge2, 0L);
  498.  
  499.     OutputString( kBkOverwriteStringsID, kOverwrite3, 0L);
  500.  
  501.     testH = (shortHandle)NewHandle(kArrayMax * sizeof(short));
  502.     spareH = NewHandle(20);                                    // lets try and be safe by putting
  503.                                                             //    another handle beyond the first
  504.     OutputString( kBkOverwriteStringsID, kOverwrite4, 0L);
  505.     for (loop = 0; loop < kArrayMax+1; loop++)
  506.         (*testH)[loop] = (loop + 25);
  507.  
  508.     if (active)
  509.         OutputString( kBkOverwriteStringsID, kOverwrite5, 0L);
  510.  
  511.     DisposeHandle((Handle) spareH);
  512.     DisposeHandle((Handle) testH);
  513.  
  514.     DetectedMsgs();
  515.  
  516.     OutputString( kBkOverwriteStringsID, kOverwrite8, 0L);
  517.     if (saveStateH)
  518.         {
  519.         QCSetState(saveStateH);                        // if successful, we don't dispose of it
  520.         QCDisposeState(saveStateH);
  521.         }
  522. }
  523.  
  524. /*________________________________________________________________________________
  525.  
  526.     DetectedMsgs()
  527.  
  528.     info:     Display the appropriate error detection msg (Common to all tests)
  529.  
  530. ________________________________________________________________________________*/
  531. void    DetectedMsgs(void)
  532. {
  533.     if (gQCDetectedErr)
  534.         OutputString( kStringsID, kDetected, 0L);            // the error was detected
  535.     else
  536.         OutputString( kStringsID, kDetectionOff, 0L);        // nope, nothing was caught
  537. }
  538.  
  539. #pragma mark -
  540.  
  541. /*________________________________________________________________________________
  542.     InstallHandler()
  543.  
  544.     info:    Routine to install a QC error handler. This routine does the right thing
  545.             for PowerPC or 68k code installing an error handler.  In the case of PPC
  546.             code, the UPP created is passed back and is to be given to RemoveHandler()
  547.             when the error handler is to be removed.
  548. ________________________________________________________________________________*/
  549. QCCallBackUPP InstallHandler(void)
  550. {
  551.     QCCallBackUPP    procP;
  552.  
  553.     procP = NewQCCallBackProc(MyErrorHandler);
  554.  
  555.     QCInstallHandler( procP, SetCurrentA5());
  556.  
  557.     return (procP);
  558. }
  559.  
  560. /*________________________________________________________________________________
  561.     RemoveHandler()
  562.  
  563.     info:    Routine to install a QC error handler. This routine does the right thing
  564.             for PowerPC or 68k code installing an error handler.  In the case of PPC
  565.             code, the UPP created is passed back and is to be given to RemoveHandler()
  566.             when the error handler is to be removed.
  567.  
  568.     NOTE:    You're going to get an 'unused variable' warning on 'procP' if building
  569.             for 68k.  We could put something in to reference 'procP' for 68k builds
  570.             but that'd just be added code.  So please ignore the warning.
  571. ________________________________________________________________________________*/
  572. void RemoveHandler(QCCallBackUPP procP)
  573. {
  574. #pragma unused (procP)
  575.  
  576.     QCRemoveHandler(procP);
  577.     #ifdef    __powerc
  578.         if (procP)
  579.             DisposeRoutineDescriptor(procP);
  580.     #endif
  581. }
  582.  
  583. /*________________________________________________________________________________
  584.     MyErrorHandler()
  585.  
  586.     info:    Sample QC Error Handler called by QC when an error has been detected.
  587. ________________________________________________________________________________*/
  588. Boolean    MyErrorHandler(QCPBPtr paramBlock)
  589. {
  590.     long        oldA5;
  591.  
  592.     oldA5 = SetA5( paramBlock->data);
  593.  
  594.     gQCDetectedErr = paramBlock->error;
  595.  
  596.     SetA5(oldA5);
  597.  
  598.     // If we return true here QC will assume we handled the error ourselves and it
  599.     //    will not report anything errors to the user itself (beep or debug break).
  600.  
  601.     return(false);
  602. }
  603.