News:

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

SIZEOF and local buffer.

Started by PauloH, April 30, 2009, 01:15:52 AM

Previous topic - Next topic

PauloH

Hi,

I'm trying to copy a string from an edit control to a buffer. I coded a little procedure to it like this:


TestingProc FRAME hWnd
LOCALS szBuffer[MAX_PATH]:B

invoke RtlZeroMemory, addr szBuffer, MAX_PATH
invoke GetDlgItemText, [hWnd], EDT_1, addr szBuffer, sizeof szBuffer ; here is the problem!
invoke MessageBox, [hWnd], addr szBuffer, NULL, MB_OK

RET
ENDF


It doesn't work. OllyDbg shows me the following:

        PUSH EBP
        MOV EBP,ESP
        SUB ESP,0104h
        PUSH 0104h
        PUSH EBP
        ADD DWORD PTR SS:[ESP],-0104h
        CALL RtlZeroMemory       
        PUSH 1                               ; SIZEOF szBuffer translates into 1 and not into 0104h (MAX_PATH)!!!
        PUSH EBP
        ADD DWORD PTR SS:[ESP],-0104h
        PUSH 03E9h
        PUSH [ARG.1]
        CALL GetDlgItemTextA               
        PUSH 0
        PUSH 0
        PUSH EBP
        ADD DWORD PTR SS:[ESP],-0104h
        PUSH [ARG.1]
        CALL MessageBoxA                     
        MOV ESP,EBP
        POP EBP
        RETN 4                               



What I'm doing wrong? Is it a misuse of mine or is it a bug?

Kind regards,

PauloH

UtillMasm

push xxx
push xxx
call xxx

this hurt you, i suggest you use invoke, then use ollydbg to see it.

PauloH

... The TestingProc Frame hWnd etc is from my source code.
... The PUSH EBP etc is from a session with ollydbg.

The stack, push and pop aren't the problem. Goasm changes sizeof szBuffer which is 0104h into 01h! The same type of code with masm, using lengthof of a local buffer gives the correct answer.

Thank you anyway.

Kind regards,

PauloH.

donkey

Hi,

GoAsm does not calculate the size of LOCAL buffers the way you want, it will always return 1*Data size since the buffer begins with 0 and it is trying to return the string length + NULL terminator, roughly equivalent to the LENGTHOF operator in MASM. Instead just use MAX_PATH in your case...

invoke GetDlgItemText, [hWnd], EDT_1, addr szBuffer, MAX_PATH

Another option is to use a structure...

FILENAMEBUFFER STRUCT
    DB MAX_PATH DUP
ENDS

LOCAL szBuffer:FILENAMEBUFFER


SIZEOF szBuffer will return 260 (MAX_PATH)
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

jorgon

Author of the "Go" tools (GoAsm, GoLink, GoRC, GoBug)

PauloH

Thank you guys. Now I understand what to do and that is not a Goasm bug.

Kind regards,

PauloH

donkey

Quote from: jorgon on April 30, 2009, 07:22:06 AM
Is this a bug?


Hi Jeremy,

No, this isn't a bug, the SIZEOF operator works as documented though it is not useful for local labels as such since it returns null terminated string lengths for buffers that cannot be initialized. It is only really a problem for users who expect it to return the same value as it would in MASM, which would be the total size of the buffer regardless of initialization where LENGTHOF would return the length of the initialized string. As it is, it returns the data size since the buffer is assumed by the assembler to contain zeroes, so for example LOCAL test[128]:D would return 4 since the first byte sequentially is 0, while LOCAL test[128]:W would return 2.

EDIT:
Thinking about it I seem to remember reading somewhere that MS compilers assume uninitialized data to contain the byte sequence 0xBAADF00D, this would cause SIZEOF in GoAsm to return roughly the same size as MASM, for initialized strings it would return the length of the string, for uninitialized buffers it would return the total size.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

jorgon

#7
Hi Edgar

QuoteNo, this isn't a bug

But the result is inconsistent with this, which is the same, but in data declared in the data section:-

HELLOSTRING DB 300 DUP 0


SIZEOF HELLOSTRING would come out at 300 decimal.

Author of the "Go" tools (GoAsm, GoLink, GoRC, GoBug)

donkey

Hi Jeremy,

I hadn't realized that, I rarely make use of the SIZEOF operator outside of structures, the same was true when I used MASM. Actually I can't think of a single instance where I've used it for buffer sizes. However, you're right, the result is ambiguous, in some cases it gives the size up to the first NULL in others the total size and when used on a LOCAL all bets are off. Perhaps a LENGTHOF operator would be the best solution for string length and make SIZEOF return the full size of the buffer.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

dedndave

i feel outdated, here
i always used......

   $-label

jj2007

#10
Quote from: donkey on April 30, 2009, 01:30:14 PM

I seem to remember reading somewhere that MS compilers assume uninitialized data to contain the byte sequence 0xBAADF00D


Interesting. When did you read that, 1st of April? At a McDonald's??  :wink

<MASM code is not relevant to this discussion and was removed...- Donkey>

dedndave

they may have done that in the old days, but 0's pack or compress much better
i seem to recall stack space filled with "STACK STACK " or something, but i always thought the programmer did it
i have seen BAAD - never saw F00D
in little endian, it may not have registered in my head - lol
0D F0 AD BA
or
AD BA 0D F0

MichaelW

In my test with Visual C++ Toolkit 2003 the uninitialized data contained garbage.

#include <windows.h>
int main(void)
{
    byte x[100];
    int i;
    for ( i=0; i<100; i++ )
        printf( "%02x", x[i] );
    getch();
    return 0;
}


d8072f00b00b2f0078012f0050072f0058072f0088000000000000008c2f40008c2f400068d1fc77
00002f0050072f003546597cd0fe120001000000999e360000000000e0fe1200bb4b4000d0fe1200
0490400097af9c809200000010830ef800cac901


eschew obfuscation

dedndave

i don't think that is garbage, exactly - at least not inside the exe file
it looks like code
the uninitialized data area may not exist at all until the OS loads the exe
that would be prefered, as the exe file would be smaller
at that point, it may be whatever was in memory at the time

donkey

#14
Quote from: jj2007Interesting. When did you read that, 1st of April? At a McDonald's??

Actually I found several references but it was for the heap, it was quite a while ago so my memory was a bit off...

http://www.codeguru.com/cpp/w-p/win32/tutorials/article.php/c9535
QuoteBut, HeapAlloc() will allocate even more bytes: 8 bytes below the requested block (that is, at a lower address) and 32 above it (that is, at a bigger address). It also initializes the requested block to 0xBAADF00D (bad food).

22,000 Google hits for BAADF00D initialized data:

http://www.google.ca/search?q=BAADF00D

Edgar
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable