summaryrefslogtreecommitdiff
path: root/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/helper.cpp
blob: d965ca7a5116eaf43fe8dfe09bd22710ff8e53bd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

/*=============================================================
**
** Source: helper.c
**
** Purpose: This helper process sets up a several blocks of memory, 
** then uses a file to tell its parent process where that memory is 
** So it can do a WriteProcessMemory on it. When the parent process is done 
** we check here that it was written properly.
**
**
**============================================================*/

#include "commonconsts.h"

#include <palsuite.h>

struct allhandles_t 
{
    HANDLE hEvToHelper;
    HANDLE hEvFromHelper;
    char *valuesFileName;
};


/* function: wpmDoIt
 *
 * This is a general WriteProcessMemory testing function that sets up
 * the RAM pointed to and tells the companion process on the other end
 * of the handles in 'Comms' to attempt to alter 'lenDest' bytes at
 * '*pDest'.
 *
 * '*pBuffer'[0..'lenBuffer'] is expected to be a guard region
 * surrounding the '*pDest'[0..'lenDest'] region so that this function
 * can verify that only the proper bytes were altered.
 */

int wpmDoIt(struct allhandles_t Comms,
         char * pBuffer, unsigned int lenBuffer, 
         char * pDest, unsigned int lenDest, 
         const char* storageDescription)
{
    char *pCurr;
    FILE *commsFile;
    DWORD dwRet;

    if (pBuffer > pDest || lenDest > lenBuffer)
    {
        Trace("WriteProcessMemory::DoIt() test implementation: "
              "(pBuffer > pDest || lenDest > lenBuffer)\n");
        return FALSE;
    }

    /* set up the storage */
    memset(pBuffer, guardValue, lenBuffer);
    memset(pDest, initialValue, lenDest);

    /* tell the parent what RAM to adjust */
    if(!(commsFile = fopen(Comms.valuesFileName, "w"))) 
    {
        Trace("WriteProcessMemory: fopen of '%S' failed (%u). \n",  
             Comms.valuesFileName, GetLastError());
        return FALSE;
    }
    if (!fprintf(commsFile, "%u %u '%s'\n", 
                 pDest, lenDest, storageDescription))
    {
        Trace("WriteProcessMemory: fprintf to '%S' failed (%u). \n",  
             Comms.valuesFileName, GetLastError());
        return FALSE;
    }
    PEDANTIC1(fclose, (commsFile));

    /* Tell the parent the data is ready for it to adjust */
    PEDANTIC(ResetEvent, (Comms.hEvToHelper)); 
    PEDANTIC(SetEvent, (Comms.hEvFromHelper)); 

    dwRet = WaitForSingleObject(Comms.hEvToHelper, TIMEOUT); /* parent is done */
    if (dwRet != WAIT_OBJECT_0)
    {
        Trace("helper WaitForSingleObjectTest:  WaitForSingleObject "
              "failed (%u)\n", GetLastError());
        return FALSE;
    }

    /* check the stuff that SHOULD have changed */
    for (pCurr = pDest; pCurr < (pDest + lenDest); pCurr++) 
    {
        if ( *pCurr != nextValue)
        {
            Trace("When testing '%s': alteration test failed "
                  "at %u offset %u. Found '%c' instead of '%c'\n.",
                  storageDescription, pDest, pCurr - pDest, *pCurr, nextValue);
            Trace(" 'Altered' string: '%.*s'\n",lenBuffer, pBuffer);
            return FALSE;
        }
    }
    /* check the stuff that should NOT have changed */
    for (pCurr = pBuffer; pCurr < pDest; pCurr++ ) 
    {
        if ( *pCurr != guardValue)
        {
            Trace("When testing '%s': leading guard zone test failed "
                  "at %u offset %u. Found '%c' instead of '%c'\n.",
                  storageDescription, pDest, pCurr - pBuffer, *pCurr, guardValue);
            Trace(" 'Altered' string: '%.*s'\n",lenBuffer, pBuffer);
            return FALSE;
        }
    }
    for (pCurr = pDest + lenDest; pCurr < (pBuffer + lenBuffer); pCurr++ ) 
    {
        if ( *pCurr != guardValue)
        {
            Trace("When testing '%s': trailing guard zone test failed "
                  "at %u offset %u. Found '%c' instead of '%c'\n.",
                  storageDescription, pDest + lenDest, pCurr - pBuffer, *pCurr, guardValue);
            Trace(" 'Altered' string: '%.*s'\n",lenBuffer, pBuffer);
            return FALSE;
        }
    }

    return TRUE;
}

int __cdecl main(int argc, char *argv[])
{
     
    BOOL  success = TRUE;  /* assume success */
    struct allhandles_t Comms = {0,0,0} ;

    /* variables to track storage to alter */
    char *pTarget = NULL;
    unsigned int sizeTarget;

    if(0 != (PAL_Initialize(argc, argv)))
    {
        return FAIL;
    }

    /* hook up with the events created by the parent */
    Comms.hEvToHelper = OpenEventW(EVENT_ALL_ACCESS, 0, szcToHelperEvName);
    if (!Comms.hEvToHelper) 
    {
        Fail("WriteProcessMemory: OpenEvent of '%S' failed (%u). "
             "(the event should already exist!)\n", 
             szcToHelperEvName, GetLastError());
    }
    Comms.hEvFromHelper = OpenEventW(EVENT_ALL_ACCESS, 0, szcFromHelperEvName);
    if (!Comms.hEvToHelper) 
    {
        Trace("WriteProcessMemory: OpenEvent of '%S' failed (%u). "
              "(the event should already exist!)\n",  
              szcFromHelperEvName, GetLastError());
        success = FALSE;
        goto EXIT;
    }
    Comms.valuesFileName = argv[1];

    {
        char autoAllocatedOnStack[51];

        /* Get the parent process to write to the local stack */
        success &= wpmDoIt(Comms, autoAllocatedOnStack, 
                          sizeof(autoAllocatedOnStack),
                          autoAllocatedOnStack + sizeof(int), 
                          sizeof(autoAllocatedOnStack) - 2 * sizeof(int),
                          "const size array on stack with int sized guards");
    }

    /* Get the parent process to write to stuff on the heap */
    sizeTarget =  2 * sizeof(int) + 23 ;  /* 23 is just a random prime > 16 */
    if (!(pTarget = (char*)malloc(sizeTarget))) 
    {
        Trace("WriteProcessMemory helper: unable to allocate '%s'->%d bytes of memory"
              "(%u).\n",
              argv[3], sizeTarget, GetLastError());
        success = FALSE;
        goto EXIT;
        
    }
    success &= wpmDoIt(Comms, pTarget, sizeTarget,
                      pTarget + sizeof(int), 
                      sizeTarget - 2 * sizeof(int),
                      "array on heap with int sized guards");

    /* just to be nice try something 16 - 2 * sizeof(int) bytes long */
    {
        char autoAllocatedOnStack[16];

        /* Get the parent process to write to the local stack */
        success &= wpmDoIt(Comms, autoAllocatedOnStack, 
                          sizeof(autoAllocatedOnStack),
                          autoAllocatedOnStack + sizeof(int), 
                          sizeof(autoAllocatedOnStack) - 2 * sizeof(int),
                          "another 16 byte array on stack with int sized guards inside");
    }

    /* NOTE: Don't try 0 bytes long.  Win32 WriteProcessMemory claims
     * it writes 8 bytes in that case! */

    /* and 1 byte long... */
    {
        char autoAllocatedOnStack[1+ 2 * sizeof(int)];

        /* Get the parent process to write to the local stack */
        success &= wpmDoIt(Comms, autoAllocatedOnStack, 
                           sizeof(autoAllocatedOnStack),
                           autoAllocatedOnStack + sizeof(int), 
                           1,
                           "no bytes with int sized guards outside on stack");
    }


EXIT:
    /* Tell the parent that we are done */
    if (!DeleteFile(Comms.valuesFileName))
    {
        Trace("helper: DeleteFile failed so parent (test1) is unlikely "
             "to exit cleanly\n");
    }
    PEDANTIC(ResetEvent, (Comms.hEvToHelper)); 
    if (!SetEvent(Comms.hEvFromHelper))
    {
        Trace("helper: SetEvent failed so parent (test1) is unlikely "
              "to exit cleanly\n");
    }

    free(pTarget);
    PEDANTIC(CloseHandle, (Comms.hEvToHelper));
    PEDANTIC(CloseHandle, (Comms.hEvFromHelper));

    if (!success) 
    {
        Fail("");
    }

    PAL_Terminate();

    return success ? PASS : FAIL;
}