Huge thanks to our Platinum Members Endace and LiveAction,
and our Silver Member Veeam, for supporting the Wireshark Foundation and project.

Ethereal-dev: [Ethereal-dev] LDAP/SIP truncation problems ... snprintf and vsnprintf non-term

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Ronald Henderson <Ronald.Henderson@xxxxxxxxxxxxxxxx>
Date: Wed, 18 Dec 2002 13:37:45 -0500
Folks:

Marting Regner and I need your desired coding fix based on discovering the
cause of blank lines or garbage data at the end of the value that appears on
the windows platform for LDAP and SIP protocols when values exceed the
ITEM_LABEL_LENGTH limit. This behavior is different for the Linux platform.
The C runtime libraries do not insert a termination character '\0' for the
snprintf() and vsnprintf()  functions if the value exceeds the size limit.
These functions are found in the "proto.c" file. Currently the returned
value is not used for these functions in "proto.c"

Windows:
=======

For the windows platform, if a value exceeds the size limit (in our case
ITEM_LABEL_LENGTH) the associated character buffer used in the snprintf() or
vsnprinf() function will not be null terminated. This causes no data to be
displayed or extra printable characters to be displayed at the end of the
value.

Reason for blank line: On the windows platform if a value to be displayed
contains a non-printable character (i.e. octet value greater than 0x7F) no
data will be displayed at all for that value. Since the snprintf() or
vnsprintf() don't terminate the char buffer if the value is greater than:
ITEM_LABEL_LENGTH printing for that value will continue until a null
terminating character is found. If a non-printing character exists from the
beginning of the of the char buffer to the false null terminating character
no data is printed. A simple modification to force printing under windows
for FT_STRING types is to change code in the function  format_text(const
guchar *string, int len) file strutil.c

From:
if (isprint(c)) {

To:
if (isprint(c) && (c < 128)) {

This forces octal character printing (i.e. \nnn) for non-printal characters
and the data for that value is now displayed...

Reason for extra characters at end of value: Once again printing will
continue until a null character is found. If all characters are printable
extra garbage printable characters will be found at the end of the value...

Here is microsoft's definition of the snprintf() function... 

Microsoft snprintf() (MSVC 6.0) docs:
===========================
...
_vsnprintf and _vsnwprintf return the number of characters written, not
including the terminating null character, or a negative value if an output
error occurs. For _vsnprintf, if the number of bytes to write exceeds
buffer, then count bytes are written and -1 is returned.
...



Linux:
======
For the linux platform the behavior for the snprintf() and vsnprintf() are
the similar as far as the null terminating character is concern (i.e. there
will be none if the value exceeds the size limit). But what is different is
the non-printable character are shown as garbage characters, therefore no
blank lines. Extra characters will also show up until a null termination
character is found.

Linux: Man Page for snprintf()
==============================
...
 Return value
       Upon successful return, these functions return the number of
characters printed  (not  including  the  trailing  '\0'  used  to  end
output to strings).  The functions snprintf and vsnprintf do not write more
than       size  bytes (including the trailing '\0').  If the output was
truncated due to this limit then the return value is  the  number  of
characters (not  including the trailing '\0') which would have been written
to the final string if enough space had been available. Thus, a  return
value of  size  or  more means that the output was truncated. (See also
below under NOTES.)  If an output error is encountered, a negative  value
is returned.
...  
NOTES
       The  glibc  implementation of the functions snprintf and vsnprintf
conforms to the C99 standard, i.e.,  behaves  as  described  above,  since
glibc version 2.1. Until glibc 2.0.6 they would return -1 when the output
was truncated.
...


Questions:
=========
How would you like the fix to be in proto.c?

1) Does this check have to be corrected for every instance of snprintf() and
vsnprintf() or just for proto values that make since (i.e. FT_STRING)?

2) From what I see the check needs to be for return values of -1 or size
greater than or equal to ITEM_LABEL_LENGTH

3) Should a compiler directive be used here for a Windows build vs a Unix
build (i.e. #ifdef _WIN32)?


Looking forward to your responses....


---Ronald W. Henderson