Sujet : Re: FreeTDS port to VMS V9.x on x86?
De : arne (at) *nospam* vajhoej.dk (Arne Vajhøj)
Groupes : comp.os.vmsDate : 24. Jun 2025, 01:17:57
Autres entêtes
Organisation : A noiseless patient Spider
Message-ID : <103cqrl$1j6rb$1@dont-email.me>
References : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
User-Agent : Mozilla Thunderbird
On 6/23/2025 6:33 PM, Craig A. Berry wrote:
I haven't had time yet to dig into why the replacement wasn't working.
I did a little digging.
tds_vasprintf contains:
// fp = NLA0:
len = vfprintf(fp, fmt, ap);
// buf = malloc(len + 1)
if (vsprintf(buf, fmt, ap) != len)
return -1;
And the test fails.
And it can be recreated outside of FreeTDS.
$ type zzzz.c
#include <stdio.h>
#include <stdarg.h>
void test(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
int len_1 = vfprintf(stdout, fmt, ap);
// va_end(ap);
fprintf(stdout, " [len=%d]\n", len_1);
char buf[1000];
// va_start(ap, fmt);
int len_2 = vsprintf(buf, fmt, ap);
va_end(ap);
printf("%s [len=%d]\n", buf,len_2);
}
int main(int argc, char *argv[])
{
test("INSERT INTO t1 VALUES(%d, '%s')", 999, "XXX");
test("INSERT INTO t1 VALUES(%d, '%s')", 999, "XXX");
test("INSERT INTO t1 VALUES(%d, '%s')", 999, "XXX");
return 0;
}
$ cc zzzz
$ link zzzz
$ r zzzz
INSERT INTO t1 VALUES(999, 'XXX') [len=33]
INSERT INTO t1 VALUES(2060040508, '') [len=37]
INSERT INTO t1 VALUES(999, 'XXX') [len=33]
INSERT INTO t1 VALUES(2068038401, '') [len=37]
INSERT INTO t1 VALUES(999, 'XXX') [len=33]
INSERT INTO t1 VALUES(2068038401, '') [len=37]
It seems like vfprintf mess up ap so it is no longer good
for vsprintf.
And that is supposedly perfectly legal. C99 says:
<quote>
As the functions vfprintf, vfscanf, vprintf, vscanf, vsnprintf, vsprintf, and
vsscanf invoke the va_arg macro, the value of arg after the return is indeterminate.
</quote>
Unfortunately that means that the entire fallback algorithm
in tds_vasprintf (write to null device to find output size,
allocate buffer of correct size and then write to buffer)
is broken.
Arne