News:

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

GetPathOnly crashes if there's no "\"

Started by UlliN, January 12, 2007, 04:16:49 PM

Previous topic - Next topic

UlliN

Hi ,

GetPathOnly from  m32lib crashes if there's no "\" within the path/filename.
I've altered the code to process even filenames "c:test.dat"  or "test.dat". 

GetPathOnly proc src:DWORD, dst:DWORD

    push esi
    push edi

    xor ecx, ecx    ; zero counter
;-----------------------------------------
    mov edx, ecx                                   ; UN : edx=0 if no "\"
;-----------------------------------------
    mov esi, src
    mov edi, dst

  @@:
    mov al, [esi]   ; read byte from address in esi
    inc esi
    inc ecx         ; increment counter
    cmp al, 0       ; test for zero
    je gfpOut       ; exit loop on zero
    cmp al, "\"     ; test for "\"
    jne nxt2        ; jump over if not
    mov edx, ecx    ; store counter in ecx = last "\" offset in ecx
    jmp nxt1
;-------------------------------------------
  nxt2:                                            ; UN   test for ":"
    cmp al, ":"     ; test for "\"
    jne nxt1        ; jump over if not
    mov edx, ecx    ; store counter in ecx = last ":" offset in ecx
;-------------------------------------------   
  nxt1:
    mov [edi], al   ; write byte to address in edi
    inc edi
    jmp @B
   
  gfpOut:
    add edx, dst    ; add destination address to offset of last "\"
    mov [edx], al   ; write terminator to destination

    pop edi
    pop esi

    ret

GetPathOnly endp


Ulli

MichaelW

I can't make it "crash" on my system. When no "\" is present it returns with the destination set to the first character of the source. I don't see this as a serious problem, but IMO if no path is present then the procedure should return with the first character of the destination set to zero. Your version does so if the source contains no path and no drive spec, but both versions treat the drive spec as part of the path, which in my view it properly is not.

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .data
      src1 db "c:\masm32\m32lib\getpth.asm",0
      src2 db "c:getpth.asm",0
      src3 db "getpth.asm",0
      dest db 100 dup(0)
    .code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

_GetPathOnly proc src:DWORD, dst:DWORD

    push esi
    push edi

    xor ecx, ecx    ; zero counter
;-----------------------------------------
    mov edx, ecx                                   ; UN : edx=0 if no "\"
;-----------------------------------------
    mov esi, src
    mov edi, dst

  @@:
    mov al, [esi]   ; read byte from address in esi
    inc esi
    inc ecx         ; increment counter
    cmp al, 0       ; test for zero
    je gfpOut       ; exit loop on zero
    cmp al, "\"     ; test for "\"
    jne nxt2        ; jump over if not
    mov edx, ecx    ; store counter in ecx = last "\" offset in ecx
    jmp nxt1
;-------------------------------------------
  nxt2:                                            ; UN   test for ":"
    cmp al, ":"     ; test for "\"
    jne nxt1        ; jump over if not
    mov edx, ecx    ; store counter in ecx = last ":" offset in ecx
;-------------------------------------------   
  nxt1:
    mov [edi], al   ; write byte to address in edi
    inc edi
    jmp @B
   
  gfpOut:
    add edx, dst    ; add destination address to offset of last "\"
    mov [edx], al   ; write terminator to destination

    pop edi
    pop esi

    ret
_GetPathOnly endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    invoke GetPathOnly,ADDR src1,ADDR dest
    print ADDR dest,13,10
    invoke _GetPathOnly,ADDR src1,ADDR dest
    print ADDR dest,13,10
    invoke GetPathOnly,ADDR src2,ADDR dest
    print ADDR dest,13,10
    invoke _GetPathOnly,ADDR src2,ADDR dest
    print ADDR dest,13,10
    invoke GetPathOnly,ADDR src3,ADDR dest
    print ADDR dest,13,10
    invoke _GetPathOnly,ADDR src3,ADDR dest
    print ADDR dest,13,10

    inkey "Press any key to exit..."
    exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start


c:\masm32\m32lib\
c:\masm32\m32lib\
c
c:
g

Press any key to exit...
eschew obfuscation

UlliN

Hi Michael,

IMO EDX is set only, if there's an "/". But its always used as pointer to the terminator.
Set EDX to an arbitrary value (not 0) before calling GetPathOnly.....

Ulli





hutch--

#3
I have always had the problem with the assertion using file names like "c:test.dat" that it is not a valid path to start with without the drive designator "\"

It is documented in the help file as.

Quote
Description

GetPathOnly reads the path of a complete file path and returns the path portion in the destination buffer.

Later :


; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

comment * -----------------------------------------------------
                        Build this  template with
                       "CONSOLE ASSEMBLE AND LINK"
        ----------------------------------------------------- *

    .code

start:
   
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

    call main
    inkey
    exit

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

main proc

    LOCAL pbuf  :DWORD
    LOCAL pdst  :DWORD
    LOCAL buffer[260]:BYTE
    LOCAL dstbuf[260]:BYTE

    mov pbuf, ptr$(buffer)
    mov pdst, ptr$(dstbuf)

    chdir "\"                               ; set drive root
    invoke GetCurrentDirectory,260,pbuf
    print pbuf,13,10

    invoke GetModuleFileName,NULL,pbuf,260  ; get the apps path and file name
    print pbuf,13,10

    invoke GetPathOnly,pbuf,pdst            ; strip file name and display path.
    print pdst,13,10

    ret

main endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

end start


This outputs the following.


H:\
H:\asm3\apath\pth.exe
H:\asm3\apath\
Press any key to continue ...
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

UlliN

Hello Hutch,

I only wanted to say, that EDX has to be initialized!

Try this

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .data
      src3 db "getpth.asm",0
      dest db 100 dup(0)
    .code
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    mov edx, 11111111
    invoke GetPathOnly,ADDR src3,ADDR dest
    print ADDR dest,13,10

    inkey "Press any key to exit..."
    exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start


and you get a GPF.

Initialize EDX, and all works fine.

Regards
Ulli



hutch--

Ulli,

Thanks for the effort, the proc was originally written to handle valid paths only which always have a "\" but the mod you suggested is simple enough and does not slow the algo down so it makes sense to make it a bit more idiot proof. Here is the mod.


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

    .486                      ; create 32 bit code
    .model flat, stdcall      ; 32 bit memory model
    option casemap :none      ; case sensitive

    .code

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

GetPathOnly proc src:DWORD, dst:DWORD

    push esi
    push edi

    xor ecx, ecx    ; zero counter
    mov esi, src
    mov edi, dst
    xor edx, edx    ; zero backslash location

  @@:
    mov al, [esi]   ; read byte from address in esi
    inc esi
    inc ecx         ; increment counter
    cmp al, 0       ; test for zero
    je gfpOut       ; exit loop on zero
    cmp al, "\"     ; test for "\"
    jne nxt1        ; jump over if not
    mov edx, ecx    ; store counter in ecx = last "\" offset in ecx
  nxt1:
    mov [edi], al   ; write byte to address in edi
    inc edi
    jmp @B
   
  gfpOut:
    add edx, dst    ; add destination address to offset of last "\"
    mov [edx], al   ; write terminator to destination

    pop edi
    pop esi

    ret

GetPathOnly endp

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

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

Jibz

Just for the record, a valid path may contain no '\', but a full path must. For example "c:test.dat" refers to the file test.dat in the current directory of the C drive.

Check the section on Relative Paths in MSDN: Naming a File.