News:

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

Is there any reason this code should fail?

Started by box, June 24, 2010, 03:32:11 AM

Previous topic - Next topic

box

When I run this executable it crashes with a "test.exe has encountered a problem and needs to close.  We are sorry for the inconvenience." message without displaying a messagebox.

If I run it in OllyDBG it functions as expected, displaying the messagebox but it says INT3 command at ntdll.DbgBreakPoint somewhere in arrfree$'s GlobalFree call even though the array handle still seems to be valid.

if I uncomment the first messagebox it runs as expected, displaying both messageboxes, but still doesn't exit properly with or without the debugger.

include \masm32\include\masm32rt.inc

    .data?

dap dd ?

    .code

start:

    call main
    invoke ExitProcess, 0

main proc
;    invoke MessageBox, 0, chr$("asdf"), chr$("asdf"), 0
    mov dap, arrfile$("test.txt")

    invoke MessageBox, 0, udword$(arrtotal$(dap, 1)), chr$("dap"), 0

    mov eax, arrfree$(dap)

    ret

main endp

end start



note: test.txt contained one line of text, when I replace it with the contents of make.bat the program exits silently rather than the "encountered a problem" message.

jj2007

@box: There is indeed a problem, but knowing Hutch, he will fix it in no time. If you can't wait, try MasmBasic:

include \masm32\MasmBasic\MasmBasic.inc
Init
Recall "\Masm32\include\Windows.inc", L$()
MsgBox 0, L$(2), "The third string:", MB_OK
Exit
end start


@Hutch: The final call to GlobalFree in mov eax, arrfree$() fails for small files, see below. There is also always an access violation for arrfile$("I_dont_exist.txt")

include \masm32\include\masm32rt.inc

    .data?

dap dd ?

    .code

start:

    call main
    invoke ExitProcess, 0

main proc
;    mov dap, arrfile$("smalltest.txt") ; GPF after "Done"
    mov dap, arrfile$("\Masm32\include\Windows.inc") ; no GPF after "Done"
    ; mov dap, arrfile$("I_dont_exist.txt") ; GPF right here

    invoke MessageBox, 0, udword$(arrtotal$(dap, 1)), chr$("dap"), 0
    mov eax, arrfree$(dap)

    MsgBox 0, "Done", "Hi", MB_OK

    exit

main endp

end start

hutch--

The help file tells you the story.


Description

Load a CRLF delimited text file and write it directly to an array.


A single line is not a CRLF delimited text file.

It works if there is a CRLF and 1 character after it thus making it a 2 line file that is CRLF delimited.

If I get time I will have a play with it but I am time poor at the moment.

It actually does what its designed to do which is load a CRLF delimited text file into an array but it in the longer haul needs so protection agains using it incorrectly.

JJ, in the arrfree proc the deallocation is,


    invoke GlobalFree,[esp+4][12]   ; free the pointer array


Have I missed something here ?
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

hutch--

Here is a small test piece.

Simple text file.

test 1
test 2
test 3
test 4


Code to read it.


include \masm32\include\masm32rt.inc

    .code
  start:

    call main
    invoke ExitProcess, 0

main proc

    LOCAL acnt  :DWORD
    LOCAL pmbr  :DWORD
    LOCAL hArr  :DWORD

    push esi

    mov hArr, arrfile$("test.txt")              ; load the CRLF test file
    mov acnt, arrcnt$(hArr)                     ; count the lines
    fn MessageBox,0,str$(acnt),"Count",MB_OK

    mov esi, 1                                  ; use ESI as array index + loop counter
  @@:
    mov pmbr, arrget$(hArr,esi)                 ; get each array member by its index
    fn MessageBox,0, pmbr,"Title",MB_OK
    add esi, 1
    cmp esi, acnt
    jle @B

    mov eax, arrfree$(hArr)                     ; free the array memory
    fn MessageBox,0,str$(eax),"Return Value",MB_OK

    pop esi
    ret

main endp

end start
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

box

test 1
test 2
test 3
test 4

works with that code, although the process doesn't exit cleanly, and run in OllyDBG, the last messagebox fails to appear

test 1
a
test 2
test 3
test 4

fails outright with "test.exe has encountered a problem and needs to close.  We are sorry for the inconvenience."

What happens for you when you try the second file?

jj2007

Hutch,
The test piece fails again. I wonder if I have an old version: \masm32\m32lib\arrfile.asm dates 17.05.2008, 1337 bytes...

box

arralloc was writing 4 bytes past he end of the allocated array

    jle @B

on line 45 of m32lib\arralloc.asm

changed to

    jl @B

everything seems to work now

hutch--

JJ,

Date for MASM32 distribution file is 8.9.2008.

Box,

Thanks, I will have to set the arralloc procedure up in a test piece to see what its doing. What you have suggested makes sense so I have to verify what the problem is.

Modifying the text file to the following,


test 1
1
test 2
2
test 3
3
test 4
4


Works correctly.

This is the result for the following console version of the test code.


Line count = 8
Line 1 = test 1
Line 2 = 1
Line 3 = test 2
Line 4 = 2
Line 5 = test 3
Line 6 = 3
Line 7 = test 4
Line 8 = 4
arrfree$ return value = 8
Press any key to continue ...


The console test piece.


; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

; Build as CONSOLE app

include \masm32\include\masm32rt.inc

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    .code
  start:

    call main
    inkey
    invoke ExitProcess, 0

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

main proc

    LOCAL acnt  :DWORD
    LOCAL pmbr  :DWORD
    LOCAL hArr  :DWORD

    push esi

    mov hArr, arrfile$("test.txt")              ; load the CRLF test file
    mov acnt, arrcnt$(hArr)                     ; count the lines
    print "Line count = "
    print str$(acnt),13,10

    mov esi, 1                                  ; use ESI as array index + loop counter
  @@:
    mov pmbr, arrget$(hArr,esi)                 ; get each array member by its index

    print "Line "
    print str$(esi)," = "
    print pmbr,13,10

    add esi, 1
    cmp esi, acnt
    jle @B

    mov esi, arrfree$(hArr)                     ; free the array memory

    print "arrfree$ return value = "
    print str$(esi),13,10

    pop esi
    ret

main endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

end start
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

jj2007

Quote from: hutch-- on June 24, 2010, 10:27:30 PM
JJ,

Date for MASM32 distribution file is 8.9.2008.


My installation dates 3 August 2008, so that is probably version 9 :dazzled:
One day you could place a little file called Masm32Version.txt somewhere :bg

hutch--

JJ,

After the first prototype version of the array code I rewrote the lot before the release of version 10 as I changed some very basic code in the original idea. This is the version of arralloc in MASM32 10.


; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    .486                      ; maximum processor model
    .model flat, stdcall      ; memory model & calling convention
    option casemap :none      ; case sensitive

    include \masm32\include\windows.inc
    include \masm32\include\kernel32.inc
    include \masm32\macros\macros.asm

    EXTERNDEF d_e_f_a_u_l_t__n_u_l_l_$ :DWORD

    .code       ; code section

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    align 16

arralloc proc mcnt:DWORD

  ; ----------------------------------------------------------------
  ; return values = handle of pointer array or 0 on allocation error
  ; ----------------------------------------------------------------
    push esi

    mov eax, mcnt                               ; load the member count into EAX
    add eax, 1                                  ; correct for 1 based array
    lea eax, [0+eax*4]                          ; multiply it by 4 for memory size

    invoke GlobalAlloc,GMEM_FIXED,eax
    mov esi, eax

    test eax, eax                               ; if allocation failure return zero
    jz quit

    mov eax, esi
    mov ecx, mcnt
    mov DWORD PTR [eax], ecx                    ; write count to 1st member

    xor edx, edx
  @@:
    add edx, 1                                  ; write adress of null string to all members
    mov [eax+edx*4], OFFSET d_e_f_a_u_l_t__n_u_l_l_$
    cmp edx, ecx
    jle @B

    mov eax, esi                                ; return pointer array handle

  quit:
    pop esi

    ret

arralloc endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    end
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

jj2007

Quote from: hutch-- on June 24, 2010, 10:45:29 PM
JJ,

After the first prototype version of the array code I rewrote the lot before the release of version 10 as I changed some very basic code in the original idea. This is the version of arralloc in MASM32 10.


Hutch,

At home I have version 9, at work version 10, and that is the latest one indeed. The exception happens in a non-predictable way, but in any case the little modification by box seems to fix the problem. The exception for non-existant files persists, though.

Best,
Jochen