News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

IsBadReadPtr and strcopy routines

Started by jj2007, February 22, 2009, 10:17:04 PM

Previous topic - Next topic

jj2007

Quote from: drizz on February 24, 2009, 09:03:36 PM
The answer is:

1. yes it can read past end of the string if the address it reads from is aligned on the access boundary


2. yes it can read past end of the string if the address it reads from is not aligned on the access boundary, provided that the memory was not allocated with VirtualAlloc but rather with HeapAlloc

3. no it will go bang in your face even if the address it reads from is aligned on the access boundary in those rare cases where the virtual-allocated memory does not contain a zero delimiter.

japheth

Quote from: jj2007 on February 24, 2009, 09:55:17 AM
Your answer is correct, but it applies to all strlen functions, even those that read byte by byte. This thread was inspired by an earlier thread asking "can we use this dangerous SSE2 stuff that may read 15 bytes beyond the end of the string". Yes, we can, because there is no principal difference between an algo that reads 1 and another one that reads 15 bytes "beyond". Of course, there is a tiny chance that it may fail - especially with "intolerant" VirtualAlloc; but the only alternative would be not using any strlen function.

This is nonsense. The X'00' termination byte of ASCIIZ strings is part of the string, it isn't "beyond".

sinsi

If you read a file into a buffer, then the act of reading it into memory validates that memory. I can see one problem only
- your text file is 4096 bytes long
- you VirtualAlloc 4096 bytes
- you make the 4097th byte 00

Using StrLen from masm32 v10 will crash if the string is misaligned, but the help doesn't say anything about alignment.

Just curious, if you get a string from windows (when it provides a buffer) can you be sure that it's dword aligned?
Light travels faster than sound, that's why some people seem bright until you hear them.

jj2007

Quote from: sinsi on February 25, 2009, 06:18:58 AM
If you read a file into a buffer, then the act of reading it into memory validates that memory. I can see one problem only
- your text file is 4096 bytes long
- you VirtualAlloc 4096 bytes
- you make the 4097th byte 00

Sinsi, you are always a source of inspiration :U

OK, I have put together a harmless little example.
- your text file is 4096 bytes long
- you VirtualAlloc a buffer that matches the size of the file (i.e. 4096 bytes)
- you read the file into the buffer
- you use lstrcat to append it to a (big fat) buffer
- you display the contents with print

Straightforward, isn't it? It works perfectly with all kinds of files. Except the attached one.
(But you can make it work by deleting one of the "!" behind "Oops", thus reducing its size to 4095 bytes.)

include \masm32\include\masm32rt.inc

.data?
hFile dd ?
fSize dd ?
pMem dd ?
MbRetAddr dd ?
BigFatBuffer dd 10000h dup(?)

.code
start:
mov hFile, fopen("MyText.txt") ; we open a textfile
.if eax==INVALID_HANDLE_VALUE
MsgBox 0, LastError$(), "No such file:", MB_OK
.else
mov fSize, fsize(hFile) ; allocate a buffer for reading in the file
.if eax!=4095 && eax!=4096 ; we are testing the bounds
MsgBox 0, "Check your file size", "Hi", MB_OK
.endif
invoke VirtualAlloc, NULL, fSize, MEM_COMMIT, PAGE_READWRITE
.if eax==0
MsgBox 0, LastError$(), "VirtualAlloc failure:", MB_OK
.else
mov pMem, eax ; we keep a pointer to the buffer
.if fread(hFile, pMem, fSize)!=fSize
MsgBox 0, LastError$(), "There was an error reading the file:", MB_OK
.endif
fclose hFile
print "The file size is " ; you will see this message
print str$(fSize), " bytes", 13, 10
invoke lstrcpy, offset BigFatBuffer, chr$("Here is the content:", 13, 10)

; all fine until we are trying to append the contents of our file -
; see below for details:
invoke lstrcat, offset BigFatBuffer, pMem

print offset BigFatBuffer ; you should see the content now

print chr$(13,10,13,10, "---- OK ----", 13, 10)
invoke VirtualFree, pMem, 0, MEM_RELEASE
.endif
.endif
getkey
exit
end start


Here is what Olly will tell you about the reason why you can't see the content:

Address                  Hex dump                   Command
7C834D56                  8A08                      mov cl, byte ptr [eax]   ; ***** inner loop *********
7C834D58                  40                        inc eax
7C834D59                  84C9                      test cl, cl
7C834D5B                 75 F9                     jne short kernel32.7C834D56   ; ***** inner loop *********
; ------- try setting a breakpoint after the jne - you will never see it! ---------
7C834D5D                  2BC2                      sub eax, edx

; ------- you will see this one only if you "animate" for some minutes -------
; ntdll.KiUserExceptionDispatcher(pExceptionRecord,pContext)
KiUserExceptionDispatche  8B4C24 04                 mov ecx, dword ptr [esp+4]
7C90EAF0                  8B1C24                    mov ebx, dword ptr [esp]
Access violation in KERNEL32 ignored on request - passed to application

[attachment deleted by admin]