Bug #55999 vprintln_socket fails to print strings > 999 bytes
Submitted: 16 Aug 2010 8:39 Modified: 19 May 2021 21:41
Reporter: Magnus Blåudd Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Cluster: Cluster (NDB) storage engine Severity:S2 (Serious)
Version:mysql-5.1-telco-6.2 OS:Any
Assigned to: Magnus Blåudd CPU Architecture:Any
Tags: 6.2.19

[16 Aug 2010 8:39] Magnus Blåudd
Description:
The functions 'vprintln_socket' and 'vprint_socket' in socket_io.cpp can't print strings longer than 999 bytes. When the result of the format string + varargs input are longer than the stack allocated buffer(which is 1000 bytes), the function will allocate a buffer that is big enough and call 'vsnprintf' a second time. Unfortunately the first call to 'vsnprintf' has modified the vararg list and the second call will print random junk from the stack.

How to repeat:
const char* string_longer_than_1000_bytes = "LOOOONG.... <snip> ...STRING";

vprintln_socket(socket, "%s", string_longer_than_1000_bytes);

^ will print junk to the socket.

Suggested fix:
The problem comes from having a function which takes a va_list instead of the vararg format ..., this prevents using va_start/va_end before and after each call to 'vsnprintf'.

Suggested solutions:
1) Rewrite the callers of 'vprintfln_socket' to do the mallocs if buffer are too small and thus allowing each call to 'vsnprintf' be surrounded by va_start/va_end. There doesn't seem to be many users of this function(i.e it's mainly used by SocketOutputStream) and it should be possible to collapse the two functions.

2) Use the 'va_copy' function from C99 to take a copy of the va_list before the first vsnprintf calls and use the copy in the second call. Requires a fairly modern compiler and is not yet available in Visual C++(although it seems that could be implemented with an assignment).
[19 May 2021 21:41] Jon Stephens
Fixed in NDB 8.0.27.

Refactoring only, no user-visible changes to document.

Closed.