Merge ~dougmurray/epics-base:fix-1943245 into ~epics-core/epics-base/+git/epics-base:7.0

Proposed by Doug Murray
Status: Needs review
Proposed branch: ~dougmurray/epics-base:fix-1943245
Merge into: ~epics-core/epics-base/+git/epics-base:7.0
Diff against target: 168 lines (+94/-35)
2 files modified
modules/libcom/src/misc/epicsString.c (+85/-33)
modules/libcom/test/epicsStringTest.c (+9/-2)
Reviewer Review Type Date Requested Status
Andrew Johnson Needs Fixing
Review via email: mp+422030@code.launchpad.net

Commit message

Fixes lp: #1943245

To post a comment you must log in.
Revision history for this message
Andrew Johnson (anj) wrote :

See comments inline below...

review: Needs Fixing
~dougmurray/epics-base:fix-1943245 updated
ccba97b... by Doug Murray

Fix up previous commit with added comment
Remove older routine, replaced by new version; added
comment from updated routine description.

Unmerged commits

ccba97b... by Doug Murray

Fix up previous commit with added comment
Remove older routine, replaced by new version; added
comment from updated routine description.

7abe056... by Doug Murray

#1943245 epicsStrnEscapedFromRaw may print inclomplete escape sequences
Fixed a problem where a partial escape sequence could be added to
a string. Rather than checking for the limit when adding each
character, the check is made for the entire sequence.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/modules/libcom/src/misc/epicsString.c b/modules/libcom/src/misc/epicsString.c
index ca61d9b..1854874 100644
--- a/modules/libcom/src/misc/epicsString.c
+++ b/modules/libcom/src/misc/epicsString.c
@@ -117,46 +117,98 @@ done:
117 return ndst;117 return ndst;
118}118}
119119
120int epicsStrnEscapedFromRaw(char *dst, size_t dstlen, const char *src,120/*
121 size_t srclen)121 * expand the given character.
122 * Place the expansion in *dest, which
123 * must be at least 5 characters long
124 *
125 * Returns: number of characters produced.
126 */
127static int translateEscapedChar( char c, char *dest)
122{128{
123 int rem = dstlen;129 static const char hex[] = "0123456789abcdef";
124 int ndst = 0;130 char *ptr = dest;
131 int ret = 0;
125132
126 if (dst == src)133 if( ptr == NULL)
127 return -1;134 return 0;
128135
129 while (srclen--) {136 *ptr++ = '\\';
130 static const char hex[] = "0123456789abcdef";137 switch( c) {
131 int c = *src++;
132 #define OUT(chr) ndst++; if (--rem > 0) *dst++ = chr
133
134 switch (c) {
135 case '\a': OUT('\\'); OUT('a'); break;
136 case '\b': OUT('\\'); OUT('b'); break;
137 case '\f': OUT('\\'); OUT('f'); break;
138 case '\n': OUT('\\'); OUT('n'); break;
139 case '\r': OUT('\\'); OUT('r'); break;
140 case '\t': OUT('\\'); OUT('t'); break;
141 case '\v': OUT('\\'); OUT('v'); break;
142 case '\\': OUT('\\'); OUT('\\'); break;
143 case '\'': OUT('\\'); OUT('\''); break;
144 case '\"': OUT('\\'); OUT('\"'); break;
145 case '\0': OUT('\\'); OUT('0'); break;
146 default:138 default:
147 if (isprint(c & 0xff)) {139 if( isprint( c & 0xff)) {
148 OUT(c);140 *--ptr = c;
149 break;141 ptr++;
142 ret = 1;
143 } else {
144 *ptr++ = 'x';
145 *ptr++ = hex[(c >> 4) & 0x0f];
146 *ptr++ = hex[ c & 0x0f];
147 ret = 4;
150 }148 }
151 OUT('\\'); OUT('x');149 break;
152 OUT(hex[(c >> 4) & 0x0f]);150
153 OUT(hex[ c & 0x0f]);151 case '\a': *ptr++ = 'a'; ret = 2; break;
152 case '\b': *ptr++ = 'b'; ret = 2; break;
153 case '\f': *ptr++ = 'f'; ret = 2; break;
154 case '\n': *ptr++ = 'n'; ret = 2; break;
155 case '\r': *ptr++ = 'r'; ret = 2; break;
156 case '\t': *ptr++ = 't'; ret = 2; break;
157 case '\v': *ptr++ = 'v'; ret = 2; break;
158 case '\\': *ptr++ = '\\'; ret = 2; break;
159 case '\'': *ptr++ = '\''; ret = 2; break;
160 case '\"': *ptr++ = '"'; ret = 2; break;
161 case '\0': *ptr++ = '0'; ret = 2; break;
162 }
163
164 *ptr = 0;
165 return ret;
166}
167
168/**
169 * Copy string, converting non-printable characters into their escape sequence
170 * source string.
171 *
172 * epicsStrnEscapedFromRaw does the opposite of epicsStrnRawFromEscaped: It tries
173 * to copy strlen characters from the string src into a buffer dst of size dstlen,
174 * converting non-printable characters into C-style escape sequences. A zero byte
175 * will not terminate the input string. The output string will be zero-terminated
176 * as long as dstlen is non-zero. No more than dstlen characters will actually be
177 * written into the output buffer, although all the characters in the input string
178 * will be read. The return value is the number of characters that would have been
179 * stored in the output buffer if it were large enough, or a negative value if dst
180 * == src. In-place translations are not allowed since the escaped results will
181 * usually be larger than the input string.
182 *
183 * The following escaped character constants will be used in the output:
184 * \a \b \f \n \r \t \v \\ \' \"
185 *
186 * All other non-printable characters appear as hexadeimal escapes in form \xNN
187 * where NN are two hex digits (0-9, a-f). Non-printable characters are
188 * determined by the C runtime library’s isprint() function.
189 */
190int epicsStrnEscapedFromRaw(char *dst, size_t dstlen, const char *src, size_t srclen)
191{
192 char expanded[6];
193 int remain = dstlen;
194 int cnt = 0;
195
196 if( src == dst)
197 return -1;
198
199 for( int i = 0; i < srclen; i++) {
200 int num = translateEscapedChar( src[i], expanded);
201 if( num < remain) {
202 strcpy( dst, expanded);
203 remain -= num;
204 dst += num;
154 }205 }
155 #undef OUT206 cnt += num;
156 }207 }
157 if (dstlen)208
158 *dst = '\0';209 if( dstlen != 0)
159 return ndst;210 *dst = 0;
211 return cnt;
160}212}
161213
162size_t epicsStrnEscapedFromRawSize(const char *src, size_t srclen)214size_t epicsStrnEscapedFromRawSize(const char *src, size_t srclen)
diff --git a/modules/libcom/test/epicsStringTest.c b/modules/libcom/test/epicsStringTest.c
index 7abffa3..185d0b5 100644
--- a/modules/libcom/test/epicsStringTest.c
+++ b/modules/libcom/test/epicsStringTest.c
@@ -155,7 +155,7 @@ MAIN(epicsStringTest)
155 char *s;155 char *s;
156 int status;156 int status;
157157
158 testPlan(427);158 testPlan(431);
159159
160 testChars();160 testChars();
161161
@@ -244,10 +244,17 @@ MAIN(epicsStringTest)
244244
245 memset(result, 'x', sizeof(result));245 memset(result, 'x', sizeof(result));
246 status = epicsStrnEscapedFromRaw(result, 4, ABCD, 5);246 status = epicsStrnEscapedFromRaw(result, 4, ABCD, 5);
247 testOk(status == 6, "esc(\"ABCD\", 5) -> %d (exp. 8)", status);247 testOk(status == 6, "esc(\"ABCD\", 5) -> %d (exp. 6)", status);
248 testOk(result[3] == 0, " 0-terminated");248 testOk(result[3] == 0, " 0-terminated");
249 testOk(result[4] == 'x', " No overrun");249 testOk(result[4] == 'x', " No overrun");
250250
251 memset(result, 'x', sizeof(result));
252 status = epicsStrnEscapedFromRaw(result, 5, "ABC\"DEF", 6);
253 testOk(status == 7, "esc(\"ABC\\\"DEF\", 5) -> %d (exp. 7)", status);
254 testOk(result[3] != '\\', " no partial escape sequence");
255 testOk(result[4] == 0, " 0-terminated");
256 testOk(result[5] == 'x', " No overrun");
257
251 testDiag("Testing raw = epicsStrnRawFromEscaped(out, 4, ...)");258 testDiag("Testing raw = epicsStrnRawFromEscaped(out, 4, ...)");
252259
253 memset(result, 'x', sizeof(result));260 memset(result, 'x', sizeof(result));

Subscribers

People subscribed via source and target branches