News:

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

A little wsprintf function replacement

Started by bigboss-62, January 23, 2009, 08:40:12 AM

Previous topic - Next topic

bigboss-62

Hello guys...
The wsprintf function is very cool, but it destroy most of registers.
The most important in this function is the conversion, and the only needed return value is the size of formatted buffer.
I have written the following prototype to include some functions of wsprintf, and the only modified value in return was eax, which contains the size of buffer.
Currently supports:
- %s (string)
- %??d (decimal, (unsigned for the moment) up to 16 chars displayed)
- %??X (haxadecimal, up to 16 chars displayed)

The working method is like the original wsprintf function...
Any comments / ideas are welcome...

Modified by BIGBOSS: The source code is now in a zip file as attachment

[attachment deleted by admin]

ToutEnMasm

Hello,
http://msdn.microsoft.com/en-us/library/ms647550(VS.85).aspx
Quote
Security Alert  Using this function incorrectly can compromise the security of your application. The string returned in lpOut is not guaranteed to be NULL-terminated. Also, avoid the %s format -- it can lead to a buffer overrun. If an access violation occurs it causes a denial of service against your application. In the worse case, an attacker can inject executable code. Consider using one of the following alternatives: StringCbPrintf, StringCbPrintfEx, StringCbVPrintf, StringCbVPrintfEx, StringCchPrintf, StringCchPrintfEx, StringCchVPrintf, or StringCchVPrintfEx. You should review Security Considerations: Windows User Interface before continuing.

You can also use string safe library

http://www.masm32.com/board/index.php?topic=8022.msg58718#msg58718



jj2007

Cute  :U

I had worked some time ago in a similar direction called float$, see this thread - but my algo accepted only one %f code.

ToutEnMasm, as far as I see he does not use the original "dangerous" wsprintf, so your comment should point to specific risks of his, not Microsoft's, code... if the length of the destination buffer is known, there are ways to prevent an overrun.

bigboss-62

Thanx jj2007... I will have a look on your float$ proto.

Special note to ToutEnMasm:
My custom proto is not using the original wsprintf proto, it just replace it for some function...
It's just for preserving "most" of registers after proto was invoqued... Just eax was modified, and it returns destination buffer length...

Of course, if destination buffer is not large enough, it may cause an overrun...

I will update it to improve cycles (up to now, too many, but may be reduced...)

bigboss-62

I have updated the source...
Now it supports:
- %s (string)
- %??d (decimal signed, up to 16 chars displayed)
- %??X (haxadecimal, up to 16 chars displayed)
- %??u (decimal, up to 16 chars displayed).

The prototype have also been renamed to _cpswsprintf.

I have compared it (using timers.asm) with standard wsprintf function, and my prototype seems to be at least twice faster than standard wsprintf prototype.

You can try it and post comparition time with standard wsprintf.

Any bug reports and ideas are welcome...

[attachment deleted by admin]

bigboss-62

#5
I have added a single test program with variable parameters using timers macro.
Here you can compare the results.


Comparator for standard wsprintf and _cpswsprintf. (XP SP3, Celeron 2.4 Ghz)[size=07pt]
* parameters: CTEXT("%s"), CTEXT("PARAMETERS").
   - wsprintf     :   257 cycles. (result: PARAMETERS).
   - _cpswsprintf :    71 cycles. (result: PARAMETERS). => faster
* parameters: CTEXT("%d"), -27194193.
   - wsprintf     :  1365 cycles. (result: -27194193).
   - _cpswsprintf :   564 cycles. (result: -27194193).  => faster
* parameters: CTEXT("%u"), 123456789.
   - wsprintf     :  1494 cycles. (result: 123456789).
   - _cpswsprintf :   641 cycles. (result: 123456789).  => faster
* parameters: CTEXT("%08X"), 123456789.
   - wsprintf     :  1222 cycles. (result: 075BCD15).
   - _cpswsprintf :   299 cycles. (result: 075BCD15).   => faster[/size]

Comparator for standard wsprintf and _cpswsprintf. (XP SP3, Pentium 4 2.8 Ghz)[size=07pt]
* parameters: CTEXT("%s"), CTEXT("PARAMETERS").
   - wsprintf     :   283 cycles. (result: PARAMETERS).
   - _cpswsprintf :    88 cycles. (result: PARAMETERS). => faster
* parameters: CTEXT("%d"), -27194193.
   - wsprintf     :  1797 cycles. (result: -27194193).
   - _cpswsprintf :   686 cycles. (result: -27194193).  => faster
* parameters: CTEXT("%u"), 123456789.
   - wsprintf     :  1978 cycles. (result: 123456789).
   - _cpswsprintf :   741 cycles. (result: 123456789).  => faster
* parameters: CTEXT("%08X"), 123456789.
   - wsprintf     :  1526 cycles. (result: 075BCD15).
   - _cpswsprintf :   248 cycles. (result: 075BCD15).   => faster[/size]


You can also report your test...

[attachment deleted by admin]

jj2007

Celeron M (Core Duo):

* parameters: CTEXT("%s"), CTEXT("PARAMETERS").
   - wsprintf     :   194 cycles. (result: PARAMETERS).
   - _cpswsprintf :    74 cycles. (result: PARAMETERS).
* parameters: CTEXT("%d"), -27194193.
   - wsprintf     :   717 cycles. (result: -27194193).
   - _cpswsprintf :   406 cycles. (result: -27194193).
* parameters: CTEXT("%u"), 123456789.
   - wsprintf     :   768 cycles. (result: 123456789).
   - _cpswsprintf :   415 cycles. (result: 123456789).
* parameters: CTEXT("%08X"), 123456789.
   - wsprintf     :   673 cycles. (result: 075BCD15).
   - _cpswsprintf :   327 cycles. (result: 075BCD15).

Mark Jones

AMD x2 4000+ x64, WinXP x32 SP3:

* parameters: CTEXT("%s"), CTEXT("PARAMETERS").
   - wsprintf     :   205 cycles. (result: PARAMETERS).
   - _cpswsprintf :    96 cycles. (result: PARAMETERS).
* parameters: CTEXT("%d"), -27194193.
   - wsprintf     :  1011 cycles. (result: -27194193).
   - _cpswsprintf :   513 cycles. (result: -27194193).
* parameters: CTEXT("%u"), 123456789.
   - wsprintf     :  1112 cycles. (result: 123456789).
   - _cpswsprintf :   548 cycles. (result: 123456789).
* parameters: CTEXT("%08X"), 123456789.
   - wsprintf     :   909 cycles. (result: 075BCD15).
   - _cpswsprintf :   262 cycles. (result: 075BCD15).
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

bigboss-62

I have updated the source...
Now supports:
- %s (string)
- %??d (decimal signed, up to 16 chars displayed)
- %??X (uppercase hexadecimal, up to 16 chars displayed)
- %#??X (uppercase hexadecimal ('0X' prefixed), Up to 16 chars displayed)
- %??x (lowercase hexadecimal, up to 16 chars displayed)
- %#??x (lowercase hexadecimal ('0x' prefixed), Up to 16 chars displayed)
- %??u (decimal, up to 16 chars displayed).

Compared (using timers.asm) to standard wsprintf function, it seems at least twice faster than standard..

Any bug reports and ideas are welcome...

[attachment deleted by admin]