Loading ...
Sorry, an error occurred while loading the content.

30011Re: win32 libcall() crash not found

Expand Messages
  • Bruce Mellows
    Oct 8, 2002
    • 0 Attachment
      Though I hate replying to myself...

      I suppose safe_strncpy should have begun with

      size_t length = safe_strlen(src);
      n = min(n,length);

      Bruce Mellows wrote:

      > Without the example of the GPF (so please forgive my assumptions, if
      > they are wrong)...
      >
      > I have written two functions - safe_strlen and safe_strcpy (and a main
      > to show it working).
      >
      > strlen is unsafe, because it just keeps on going and going until it
      > finds a 0 (think bunny with drum)
      >
      > strncpy (I guess) is unsafe because it calls strlen (though perhaps it
      > is inline)
      >
      > NOTE: safe_strlen is (as demonstrated) safe with any memory passed to
      > it regardless
      > NOTE: safe_strncpy adds a null terminator - this may be wrong
      > according to strncpy, I didn't bother to check (if so, sorry)
      >
      > HTH
      >
      > Bruce
      >
      > Bram Moolenaar wrote:
      >
      >> Bruce Mellows wrote:
      >>
      >>
      >>
      >>> This is the code to protect a function from a GPF.
      >>>
      >>> NOTE...
      >>>
      >>> - The critical part of the work *MUST* be done in assembler - so I
      >>> decided that it might be best if it was ALL in assembler - so it can
      >>> be in one place (the actual exception handler could have been done
      >>> in less than ten lines of C).
      >>>
      >>> - The assembler used is nasm - I could re-write it in masm if that
      >>> was preferred.
      >>>
      >>
      >>
      >> Bummer. I do like the protection against crashes, but using assembly
      >> makes it very difficult to compile Vim on various platforms (64 bit
      >> anyone?).
      >>
      >> It appears your code also catches a crash in the called function. That
      >> was not really required. Would it be possible to avoid the assembly
      >> code when we only want to check the returned pointer? There actually is
      >> a function for this (to check the validity of a pointer), but I couldn't
      >> make it work.
      >>
      >>
      >>
      >------------------------------------------------------------------------
      >
      >#include <windows.h>
      >#include <stdio.h>
      >
      >char* safe_strncpy(char* dst, const char* src, size_t n)
      >{
      > size_t index;
      >
      > for (index = 0 ; index != n && src[index] ; ++index)
      > dst[index] = src[index];
      >
      > dst[++index] = 0;
      >
      > return dst;
      >}
      >
      >size_t safe_strlen(const char* str)
      >{
      > SYSTEM_INFO si;
      > MEMORY_BASIC_INFORMATION mbi;
      >
      > size_t length = 0;
      >
      > /* get page size */
      > GetSystemInfo(&si);
      >
      > /* get memory information */
      > if (VirtualQuery(str, &mbi, sizeof(mbi)) && mbi.State == MEM_COMMIT)
      > {
      > /* pre cast these (typing savers) */
      > DWORD dwStr = (DWORD)str;
      > DWORD dwBaseAddress = (DWORD)mbi.BaseAddress;
      >
      > /* get start address of page that str is on */
      > DWORD strPage = dwStr - (dwStr - dwBaseAddress) % si.dwPageSize;
      >
      > /* get length from str to end of page */
      > DWORD pageLength = si.dwPageSize - (dwStr - strPage);
      >
      > /* work out the absolute maximum length of the string
      > * NOTE: this is not strictly true - the next block of pages
      > * may also be accessible, but this is probably good enough
      > */
      > DWORD maxLength = dwBaseAddress + mbi.RegionSize - strPage - (dwStr - strPage);
      >
      > const char* strCurr;
      > const char* memoryEnd = str + maxLength;
      >
      > for (strCurr = str ; strCurr < memoryEnd ; strCurr += pageLength, pageLength = si.dwPageSize)
      > {
      > size_t temp;
      > for (temp = 0 ; temp != pageLength && strCurr[temp] ; ++temp, ++length)
      > ;
      > if (temp != pageLength)
      > break;
      > }
      > }
      >
      > return length;
      >}
      >
      >#define BUFFER_SIZE (3 * (1<<12))
      >int main()
      >{
      > char* memory = (char*) malloc(BUFFER_SIZE);
      >
      > if (memory)
      > {
      > size_t temp;
      >
      > ::memset(memory, 'A', BUFFER_SIZE);
      > printf("%d\n", safe_strlen(memory));
      >
      > ::strcpy(memory, "TEST TEXT");
      > printf("%d\n", safe_strlen(memory));
      >
      > printf("%d\n", safe_strlen(0));
      >
      > free(memory);
      > }
      > return 0;
      >}
      >
      >
    • Show all 15 messages in this topic