This is the mail archive of the systemtap@sourceware.org mailing list for the systemtap project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix tokenize function.


Previous implementation was error-prone, because allowed returning empty
tokens (mimiced strsep()), which is fine if there is a NULL semantic.
Unfortunately SystemTap doesn't provide it in scripts and has only blank
string (""), therefore testing against it was misleading.
The solution is to return only non-empty tokens (mimic strtok()).

It was also unsafe, because NUL-termination wasn't guaranteed in the
passed string, but this is crucial for proper strsep() working.

* tapset/string.stp: Fix tokenize.
* stapfuncs.3stap.in: Update tokenize description.
* doc/langref.tex: Ditto.
---
 doc/langref.tex    |    4 ++--
 stapfuncs.3stap.in |    6 +++---
 tapset/string.stp  |   19 +++++++++++--------
 3 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/doc/langref.tex b/doc/langref.tex
index 5aefa27..5a149d1 100644
--- a/doc/langref.tex
+++ b/doc/langref.tex
@@ -3160,8 +3160,8 @@ General syntax:
 tokenize:string (input:string, delim:string)
 \end{verbatim}
 \end{vindent}
-This function returns the next token in the given input string, where 
-the tokens are delimited by one of the characters in the delim string.
+This function returns the next non-empty token in the given input string,
+where the tokens are delimited by characters in the delim string.
 If the input string is non-NULL, it returns the first token. If the input string
 is NULL, it returns the next token in the string passed in the previous call
 to tokenize. If no delimiter is found, the entire remaining input string
diff --git a/stapfuncs.3stap.in b/stapfuncs.3stap.in
index b9326fd..b5f2502 100644
--- a/stapfuncs.3stap.in
+++ b/stapfuncs.3stap.in
@@ -166,11 +166,11 @@ specified by base.  For example, strtol("1000", 16) returns 4096.  Returns 0 if
 string cannot be converted.
 .TP
 tokenize:string (str:string, delim:string)
-Return the next token in the given str string, where the tokens are delimited
-by one of the characters in the delim string.  If the str string is not blank,
+Return the next non-empty token in the given str string, where the tokens are
+delimited by characters in the delim string.  If the str string is not blank,
 it returns the first token.  If the str string is blank, it returns the next
 token in the string passed in the previous call to tokenize. If no delimiter
-is found, the entire remaining str string is returned.  Returns blank when 
+is found, the entire remaining str string is returned.  Returns blank when
 no more tokens are left.
 
 .SS TIMESTAMP
diff --git a/tapset/string.stp b/tapset/string.stp
index 35ee9fa..cf70bc6 100644
--- a/tapset/string.stp
+++ b/tapset/string.stp
@@ -70,25 +70,28 @@ function text_strn:string(input:string, len:long, quoted:long)
 
 /*
  * tokenize - Given a string and a token delimiter,
- *            return the next token in the string
- * input  String to tokenize. If NULL, returns the next token in the
- *        string passed in the previous call to tokenize().
- * delim  Token delimiter. Note this is a string, but only the first
- *        character is used as the delimiter.
+ *            return the next non-empty token in the string
+ *            or blank when no more non-empty tokens are left
+ * input  String to tokenize. If NULL, returns the next non-empty token
+ *        in the string passed in the previous call to tokenize().
+ * delim  Token delimiter. Set of characters that delimit the tokens.
  */
 function tokenize:string(input:string, delim:string)
 %{ /* pure */
 	static char str[MAXSTRINGLEN];
 	static char *str_start;
+	static char *str_end;
 	char *token = NULL;
 
 	if (THIS->input[0]) {
-		strncpy(str, THIS->input, MAXSTRINGLEN);
+		strncpy(str, THIS->input, MAXSTRINGLEN - 1);
 		str_start = &str[0];
+		*(str_end = &str[0] + strnlen(str, MAXSTRINGLEN - 1)) = 0;
 	}
-	token = strsep(&str_start, THIS->delim);
+	while ((token = strsep(&str_start, THIS->delim)) && !token[0])
+		;
 	if (token)
-		strncpy (THIS->__retvalue, token, MAXSTRINGLEN);
+		strncpy(THIS->__retvalue, token, (str_start ? str_start : str_end + 1) - token);
 %}
 
 /*
-- 
1.5.6.5


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]