From: arne@vajhoej.dk   
      
   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    
   #include    
      
   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:   
      
      
   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.   
       
      
   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   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   
|