Opened 14 years ago
Last modified 14 years ago
#1033 new Defect
Nonstandard usage of strcpy in str_util.cpp and url.cpp can result in mangled strings
Reported by: | Owned by: | ||
---|---|---|---|
Priority: | Undetermined | Milestone: | Undetermined |
Component: | Undetermined | Version: | 6.10.58 |
Keywords: | Cc: |
Description
From forum discussions, seems to be happening primarily on 64-bit linux hosts.
Found connecting to Leiden Classical:
The master file lists a scheduler with whitespace around the URL, also the file upload handler has whitespace around the URL. They both become mangled in the client_state.xml file, and as a result, BOINC cannot connect to the project properly.
In master_boinc.gorlaeus.net.xml:
<scheduler> http://boinc.gorlaeus.net/Classical_c'''gi'''/cgi </scheduler>
becomes in client_state.xml:
<scheduler_url>http://boinc.gorlaeus.net/Classical_c'''i/'''/cgi </scheduler_url>
In sched_reply_boinc.gorlaeus.net.xml
<url> http://boinc.gorlaeus.net/Classical_cgi/file_upload_h'''an'''dler </url>
becomes in client_state.xml:
<url>http://boinc.gorlaeus.net/Classical_cgi/file_upload_h'''nd'''dler </url>
I focused on the whitespace, as none of the other projects I'm using have a whitespace, and it stuck out to me. No idea how to work the code, however.
Change History (10)
comment:1 Changed 14 years ago by
comment:2 Changed 14 years ago by
(sorry, that should read "tddout" not "ttdout" in the most recent followup. I mistyped it.)
comment:3 Changed 14 years ago by
The use of strcpy in strip_whitespace: strcpy(str, str+1);
violates the C standard. One must not have the source and destination strings be (even part of) the same string. Whether the strcpy will work, do nothing, or just behave badly depends on the endianness and implementation of strcpy on the target machine.
remove_str() has the same problematic usage. If the source string length were calculated memmove() could be used and is guaranteed to work properly even with overlapping areas. Or one could code a trivial local_strcpy that could be guaranteed to work.
The following should work (making an attempt to follow local style):
+ +// strcpy() cannot be safely used on overlapping strings +// according the the C standard, +// so here we provide a simple alternate implementation. +static void +local_strcpy(char *targ, char *src) +{ + unsigned n = 0; + while (1) { + targ[n] = src[n]; + if ( !src[n]) { + break; + } + n++; + } +} // remove whitespace from start and end of a string // void strip_whitespace(char *str) { @@ -306,7 +322,7 @@ if (!str[0]) break; if (!isascii(str[0])) break; if (!isspace(str[0])) break; - strcpy(str, str+1); + local_strcpy(str, str+1); } while (1) { n = (int)strlen(str); @@ -709,7 +725,7 @@ while (1) { p = strstr(p, str); if (!p) break; - strcpy(p, p+n); + local_strcpy(p, p+n); } }
comment:4 Changed 14 years ago by
lib/url.cpp has the same mistake with strcpy.
url.cpp:260: strcpy(p, p+1);
The various other strcpy instances in lib would need a closer look ( most strcpy uses clearly have different strings as arguments, so those are fine).
(I'm not the David Anderson you know...)
comment:5 Changed 14 years ago by
It would be wiser to define local_strcpy as
static void local_strcpy(volatile char *targ, volatile char *src)
(the rest as before) to ensure against a too-smart compiler.
comment:6 Changed 14 years ago by
I found no evidence of other obviously-incorrect strcpy calls anywhere in the boinc trunk source (using a simple find-and-grep). So one can hope the two lib/ source files are the only ones with the problem.
comment:8 Changed 14 years ago by
Summary: | Possible bug in str_util.cpp in strip_whitespace → Nonstandard usage of strcpy in str_util.cpp and url.cpp can result in mangled strings |
---|
comment:9 Changed 14 years ago by
A patch which addresses the same bug in url.cpp as well as the one reported in this bug report is:
Index: str_util.h =================================================================== --- str_util.h (revision 22840) +++ str_util.h (working copy) @@ -36,6 +36,7 @@ extern char* time_to_string(double); extern char* precision_time_to_string(double); extern std::string timediff_format(double); +extern void local_strcpy(volatile char *targ, volatile char *src); inline bool ends_with(std::string const& s, std::string const& suffix) { return Index: url.cpp =================================================================== --- url.cpp (revision 22840) +++ url.cpp (working copy) @@ -257,7 +257,7 @@ while (1) { p = strstr(buf, "//"); if (!p) break; - strcpy(p, p+1); + local_strcpy(p, p+1); } n = strlen(buf); if (buf[n-1] != '/') { Index: str_util.cpp =================================================================== --- str_util.cpp (revision 22840) +++ str_util.cpp (working copy) @@ -298,6 +298,21 @@ return argc; } + +// strcpy() cannot be safely used on overlapping strings +// according the the C standard, +// so here we provide a simple alternate implementation. +void local_strcpy(volatile char *targ, volatile char *src) +{ + unsigned n = 0; + while (1) { + targ[n] = src[n]; + if ( !src[n]) { + break; + } + n++; + } +} // remove whitespace from start and end of a string // void strip_whitespace(char *str) { @@ -306,7 +321,7 @@ if (!str[0]) break; if (!isascii(str[0])) break; if (!isspace(str[0])) break; - strcpy(str, str+1); + local_strcpy(str, str+1); } while (1) { n = (int)strlen(str); @@ -709,7 +724,7 @@ while (1) { p = strstr(p, str); if (!p) break; - strcpy(p, p+n); + local_strcpy(p, p+n); } }
A separate bug report on lib/url.cpp is needed (IMO) because it assumes variously that a url will not ever exceed 255 or 1023 bytes in length. Some day one will...
comment:10 Changed 14 years ago by
Looks like part of this might be fixed in 23007
Still needs to patch url.cpp.
I'm also seeing this in client_state.xml, for the same Leiden tasks in the original report:
"ttdout" instead of "stdout," but I don't know where it gets the <command_line> from, I do not see it in any other XML files. It appears to be the same distance from the end of the string as the other malformities.