[comp.windows.ms] Possible bug in tricky use of wsprintf - MSC 6.0

karl@sugar.hackercorp.com (Karl Lehenbauer) (09/18/90)

Looks like wsprintfs of the form:

	wsprintf(outstr, "%.*s", numchars, text);

...cause a trap.  I'll be sure in a bit.  In the meantime, beware.
-- 
-- uunet!sugar!karl
-- Usenet access: (713) 438-5018

kensy@microsoft.UUCP (Ken SYKES) (09/19/90)

In article <6578@sugar.hackercorp.com> karl@hackercorp.com (Karl Lehenbauer) writes:
>Looks like wsprintfs of the form:
>
>	wsprintf(outstr, "%.*s", numchars, text);
>
>...cause a trap.  I'll be sure in a bit.  In the meantime, beware.
>-- 

The * operator is not supported by wsprintf (look at the width description
in the SDK.)  As a result it thinks numchars is the first part of the 
string address then starts grabbing values from the bogus address.  Thus
the fault.  You could get around this by writing a replacement that 
handles the '*' by using wsprintf to convert the control string to a static
string (replace *'s with the contents of numchar) then call wvsprintf to
do the actual command.  Sloppy yes, but wsprintf is not documented as a 
replacement for sprintf.  Consequently some of the features may not be
provided.

Hope this helps.

Ken Sykes
Disclaimer: The above opinions are solely my own.

marc@metapyr.UUCP ( The Karate Kid ) (09/19/90)

In article <57528@microsoft.UUCP> kensy@microsoft.UUCP (Ken SYKES) writes:
>In article <6578@sugar.hackercorp.com> karl@hackercorp.com (Karl Lehenbauer) writes:
>>Looks like wsprintfs of the form:
>>
>>	wsprintf(outstr, "%.*s", numchars, text);
>>
>>...cause a trap.  I'll be sure in a bit.  In the meantime, beware.
>>-- 
>
>The * operator is not supported by wsprintf (look at the width description
>in the SDK.)  As a result it thinks numchars is the first part of the 
>string address then starts grabbing values from the bogus address.  Thus
>the fault.  You could get around this by writing a replacement that 
>handles the '*' by using wsprintf to convert the control string to a static
>string (replace *'s with the contents of numchar) then call wvsprintf to
>do the actual command.  Sloppy yes, but wsprintf is not documented as a 
>replacement for sprintf.  Consequently some of the features may not be
>provided.
>Ken Sykes

WHOA!  The asterisk's got nothing to do with it!  If Karl is using the medium
model (as he should be :-( I hate the medium model) then the constant being
passed by "%.*s" is a NEAR pointer.  NEAR pointers passed to FAR pointer
functions cause a trap 13.  I ported a 2.11 program that had to use sprintf
for the error message system.  Converting all the sprintf's to wsprintf's
made me painfully aware of this fact.  Cast the "%.*s" to (LPSTR) and the
trap should be gone.  As a matter of fact, I just had to fix one of these
little casts that I missed the first time.  Caused "Unrecoverable Application
Error".  NOTE: All string arguments in the wsprintf call are LPSTR
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
and must be either cast that way or generated by GlobalAlloc.  This should
help.



Marc Paige
Meta/LBMS

------------------------------------------------------------------------------
"tired and shagged out from a prolonged squawk" - mpfc the parrot sketch

eav@hpindda.cup.hp.com (Eugene Veteska) (09/20/90)

/ hpindda:comp.windows.ms / karl@sugar.hackercorp.com (Karl Lehenbauer) /  7:03 pm  Sep 17, 1990 /
> Looks like wsprintfs of the form:
> 
> 	wsprintf(outstr, "%.*s", numchars, text);

I don't quit understand the syntax of the format string, but you must cast
all strings used in the format string to LPSTR.  Since wsprintf uses variable
args, there is no prototype function to type cast these.  I had this problem
before until I read the description of wsprintf which explicitly states this.
So a valid version would be:
 	wsprintf(outstr, "%.*s", numchars, (LPSTR)text);

Hope this is the cause of the problem.

Eugene Veteska
HP Information Networks Division
eav@hpda.hp.com

matts@microsoft.UUCP (Matt SAETTLER) (09/21/90)

In article <960@metapyr.UUCP> marc@metapyr.UUCP (Marc Paige - The Karate Kid ) writes:
]In article <57528@microsoft.UUCP> kensy@microsoft.UUCP (Ken SYKES) writes:
]>In article <6578@sugar.hackercorp.com> karl@hackercorp.com (Karl Lehenbauer) writes:
]>>Looks like wsprintfs of the form:
]>>
]>>	wsprintf(outstr, "%.*s", numchars, text);
]>>
]>>...cause a trap.  I'll be sure in a bit.  In the meantime, beware.
]>>-- 
]>
]>The * operator is not supported by wsprintf (look at the width description
]>in the SDK.)  As a result it thinks numchars is the first part of the 
]>string address then starts grabbing values from the bogus address.  Thus
]>the fault.  You could get around this by writing a replacement that 
]>handles the '*' by using wsprintf to convert the control string to a static
]>string (replace *'s with the contents of numchar) then call wvsprintf to
]>do the actual command.  Sloppy yes, but wsprintf is not documented as a 
]>replacement for sprintf.  Consequently some of the features may not be
]>provided.
]>Ken Sykes
]
]WHOA!  The asterisk's got nothing to do with it!  If Karl is using the medium
]model (as he should be :-( I hate the medium model) then the constant being
]passed by "%.*s" is a NEAR pointer.  NEAR pointers passed to FAR pointer
]functions cause a trap 13.  I ported a 2.11 program that had to use sprintf
]for the error message system.  Converting all the sprintf's to wsprintf's
]made me painfully aware of this fact.  Cast the "%.*s" to (LPSTR) and the
]trap should be gone.  As a matter of fact, I just had to fix one of these
]little casts that I missed the first time.  Caused "Unrecoverable Application
]Error".  NOTE: All string arguments in the wsprintf call are LPSTR
]               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
]and must be either cast that way or generated by GlobalAlloc.  This should
]help.
]

The * IS the problem.  The string constant will be automatically cast
by the compiler because the prototyp for wsprintf specifies an LPSTR.

From windows.h:
int FAR cdecl wsprintf(LPSTR,LPSTR,...);

However,  Text will have to be explicitly cast if it is not an LPSTR.

------------------
These are my own thoughts, or so I'm told to say.

poffen@sj.ate.slb.com (Russell Poffenberger) (09/22/90)

In article <40130015@hpindda.cup.hp.com> eav@hpindda.cup.hp.com (Eugene Veteska) writes:
>/ hpindda:comp.windows.ms / karl@sugar.hackercorp.com (Karl Lehenbauer) /  7:03 pm  Sep 17, 1990 /
>> Looks like wsprintfs of the form:
>> 
>> 	wsprintf(outstr, "%.*s", numchars, text);
>
>I don't quit understand the syntax of the format string, but you must cast
>all strings used in the format string to LPSTR.  Since wsprintf uses variable
>args, there is no prototype function to type cast these.  I had this problem
>before until I read the description of wsprintf which explicitly states this.

As for any format, the '%' starts the conversion specification. The '.' means
that a precision specification follows. For an 's' conversion, the entire
string is printed (up to '\0') or until the number of characters indicated by
the precision is reached. The '*' means to use an argument (in this case
numchars) as the value for the precision specification instead of hard coding
the precision into the format string. Note that since the '*' is read first,
the precision argument must precede the argument to be converted.

I haven't looked at this function yet, so I don't know if it supports that
type of conversion, but for other printf type functions, this is valid.

Russ Poffenberger               DOMAIN: poffen@sj.ate.slb.com
Schlumberger Technologies       UUCP:   {uunet,decwrl,amdahl}!sjsca4!poffen
1601 Technology Drive		CIS:	72401,276
San Jose, Ca. 95110             (408)437-5254

karl@ficc.ferranti.com (Karl Lehenbauer) (09/24/90)

In article <57528@microsoft.UUCP> kensy@microsoft.UUCP (Ken SYKES) writes:
>Sloppy yes, but wsprintf is not documented as a 
>replacement for sprintf.  Consequently some of the features may not be
>provided.  ... Hope this helps.

Thanks.  Ironically, sprintf in the standard MSC 6.0 libraries is not
documented as supporting the "%*s" feature either.  Oh well.
-- 
-- uunet!ficc!karl	"jackpot: you may have an unnecessary change record"
   uunet!sugar!karl						-- v7 diff

poffen@sj.ate.slb.com (Russell Poffenberger) (09/25/90)

In article <57612@microsoft.UUCP> matts@microsoft.UUCP (Matt Saettler) writes:
>In article <960@metapyr.UUCP> marc@metapyr.UUCP (Marc Paige - The Karate Kid ) writes:
>]In article <57528@microsoft.UUCP> kensy@microsoft.UUCP (Ken SYKES) writes:
>]>In article <6578@sugar.hackercorp.com> karl@hackercorp.com (Karl Lehenbauer) writes:
>]>>Looks like wsprintfs of the form:
>]>>
>]>>	wsprintf(outstr, "%.*s", numchars, text);
>]>>
>]>>...cause a trap.  I'll be sure in a bit.  In the meantime, beware.
>]>>-- 
>]>
>]>The * operator is not supported by wsprintf (look at the width description
>]>in the SDK.)  As a result it thinks numchars is the first part of the 
>]>string address then starts grabbing values from the bogus address.  Thus
>]>the fault.  You could get around this by writing a replacement that 
>]>handles the '*' by using wsprintf to convert the control string to a static
>]>string (replace *'s with the contents of numchar) then call wvsprintf to
>]>do the actual command.  Sloppy yes, but wsprintf is not documented as a 
>]>replacement for sprintf.  Consequently some of the features may not be
>]>provided.
>]>Ken Sykes
>]
>]WHOA!  The asterisk's got nothing to do with it!  If Karl is using the medium
>]model (as he should be :-( I hate the medium model) then the constant being
>]passed by "%.*s" is a NEAR pointer.  NEAR pointers passed to FAR pointer
>]functions cause a trap 13.  I ported a 2.11 program that had to use sprintf
>]for the error message system.  Converting all the sprintf's to wsprintf's
>]made me painfully aware of this fact.  Cast the "%.*s" to (LPSTR) and the
>]trap should be gone.  As a matter of fact, I just had to fix one of these
>]little casts that I missed the first time.  Caused "Unrecoverable Application
>]Error".  NOTE: All string arguments in the wsprintf call are LPSTR
>]               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>]and must be either cast that way or generated by GlobalAlloc.  This should
>]help.
>]
>
>The * IS the problem.  The string constant will be automatically cast
>by the compiler because the prototyp for wsprintf specifies an LPSTR.
>
>From windows.h:
>int FAR cdecl wsprintf(LPSTR,LPSTR,...);
>
>However,  Text will have to be explicitly cast if it is not an LPSTR.
>

The '*' itself is not the problem. The problem is trying to use '*' the way
most printf style calls do. The problem is in assuming that '*' meant to
look for an int variable for the precision, however wsprintf doesn't handle
that format, numchars is then being interpreted internally as the address of
a character string, and of course that won't work.

In short, wsprintf DOES NOT support the ".*" form of the precision
specification. Too bad, it can be useful. I guess you could create your own..


Russ Poffenberger               DOMAIN: poffen@sj.ate.slb.com
Schlumberger Technologies       UUCP:   {uunet,decwrl,amdahl}!sjsca4!poffen
1601 Technology Drive		CIS:	72401,276
San Jose, Ca. 95110             (408)437-5254