summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSreeram Ramachandran <sreeram@google.com>2014-09-03 15:45:59 -0700
committerSreeram Ramachandran <sreeram@google.com>2014-09-05 20:31:46 +0000
commitef12884da7c8844f8dd27cbc9c9980f685b73a2c (patch)
tree5f3de9338ff54b1c0d7adb48aae2ffe254e6fb08
parentdf11867be3f60b6bd5e24afca7820c29a28c85c7 (diff)
downloadframeworks_base-ef12884da7c8844f8dd27cbc9c9980f685b73a2c.zip
frameworks_base-ef12884da7c8844f8dd27cbc9c9980f685b73a2c.tar.gz
frameworks_base-ef12884da7c8844f8dd27cbc9c9980f685b73a2c.tar.bz2
Unescape strings properly in NsdService.
NativeDaemonEvent.unescapeArgs() was improperly skipping the terminating quote in cases like "\\", where the char preceding the quote is a backslash, but the backslash itself is escaped, so the quote is indeed an unescaped terminator. unescapeArgs() doesn't unescape "\xxx" decimal escapes used by mDNS, so fix NsdService to do that sort of unescaping explicitly (which is only applicable when it receives a "fullname", in SERVICE_RESOLVED). Bug: 16983542 Bug: 16986203 Change-Id: Idfa79749336c68424d961bc414f984c525b7e5e6
-rw-r--r--services/core/java/com/android/server/NativeDaemonEvent.java20
-rw-r--r--services/core/java/com/android/server/NsdService.java45
2 files changed, 47 insertions, 18 deletions
diff --git a/services/core/java/com/android/server/NativeDaemonEvent.java b/services/core/java/com/android/server/NativeDaemonEvent.java
index 2095152..59d50bd 100644
--- a/services/core/java/com/android/server/NativeDaemonEvent.java
+++ b/services/core/java/com/android/server/NativeDaemonEvent.java
@@ -201,20 +201,16 @@ public class NativeDaemonEvent {
}
while (current < length) {
// find the end of the word
- if (quoted) {
- wordEnd = current;
- while ((wordEnd = rawEvent.indexOf('\"', wordEnd)) != -1) {
- if (rawEvent.charAt(wordEnd - 1) != '\\') {
- break;
- } else {
- wordEnd++; // skip this escaped quote and keep looking
- }
+ char terminator = quoted ? '\"' : ' ';
+ wordEnd = current;
+ while (wordEnd < length && rawEvent.charAt(wordEnd) != terminator) {
+ if (rawEvent.charAt(wordEnd) == '\\') {
+ // skip the escaped char
+ ++wordEnd;
}
- } else {
- wordEnd = rawEvent.indexOf(' ', current);
+ ++wordEnd;
}
- // if we didn't find the end-o-word token, take the rest of the string
- if (wordEnd == -1) wordEnd = length;
+ if (wordEnd > length) wordEnd = length;
String word = rawEvent.substring(current, wordEnd);
current += word.length();
if (!quoted) {
diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java
index cf7e65c..cb1748d 100644
--- a/services/core/java/com/android/server/NsdService.java
+++ b/services/core/java/com/android/server/NsdService.java
@@ -397,8 +397,7 @@ public class NsdService extends INsdManager.Stub {
break;
case NsdManager.NATIVE_DAEMON_EVENT:
NativeEvent event = (NativeEvent) msg.obj;
- if (!handleNativeEvent(event.code, event.raw,
- NativeDaemonEvent.unescapeArgs(event.raw))) {
+ if (!handleNativeEvent(event.code, event.raw, event.cooked)) {
result = NOT_HANDLED;
}
break;
@@ -474,8 +473,14 @@ public class NsdService extends INsdManager.Stub {
case NativeResponseCode.SERVICE_RESOLVED:
/* NNN resolveId fullName hostName port txtlen txtdata */
if (DBG) Slog.d(TAG, "SERVICE_RESOLVED Raw: " + raw);
- int index = cooked[2].indexOf(".");
- if (index == -1) {
+ int index = 0;
+ while (index < cooked[2].length() && cooked[2].charAt(index) != '.') {
+ if (cooked[2].charAt(index) == '\\') {
+ ++index;
+ }
+ ++index;
+ }
+ if (index >= cooked[2].length()) {
Slog.e(TAG, "Invalid service found " + raw);
break;
}
@@ -483,6 +488,8 @@ public class NsdService extends INsdManager.Stub {
String rest = cooked[2].substring(index);
String type = rest.replace(".local.", "");
+ name = unescape(name);
+
clientInfo.mResolvedService.setServiceName(name);
clientInfo.mResolvedService.setServiceType(type);
clientInfo.mResolvedService.setPort(Integer.parseInt(cooked[4]));
@@ -541,6 +548,30 @@ public class NsdService extends INsdManager.Stub {
}
}
+ private String unescape(String s) {
+ StringBuilder sb = new StringBuilder(s.length());
+ for (int i = 0; i < s.length(); ++i) {
+ char c = s.charAt(i);
+ if (c == '\\') {
+ if (++i >= s.length()) {
+ Slog.e(TAG, "Unexpected end of escape sequence in: " + s);
+ break;
+ }
+ c = s.charAt(i);
+ if (c != '.' && c != '\\') {
+ if (i + 2 >= s.length()) {
+ Slog.e(TAG, "Unexpected end of escape sequence in: " + s);
+ break;
+ }
+ c = (char) ((c-'0') * 100 + (s.charAt(i+1)-'0') * 10 + (s.charAt(i+2)-'0'));
+ i += 2;
+ }
+ }
+ sb.append(c);
+ }
+ return sb.toString();
+ }
+
private NativeDaemonConnector mNativeConnector;
private final CountDownLatch mNativeDaemonConnected = new CountDownLatch(1);
@@ -625,10 +656,12 @@ public class NsdService extends INsdManager.Stub {
private class NativeEvent {
final int code;
final String raw;
+ final String[] cooked;
- NativeEvent(int code, String raw) {
+ NativeEvent(int code, String raw, String[] cooked) {
this.code = code;
this.raw = raw;
+ this.cooked = cooked;
}
}
@@ -644,7 +677,7 @@ public class NsdService extends INsdManager.Stub {
public boolean onEvent(int code, String raw, String[] cooked) {
// TODO: NDC translates a message to a callback, we could enhance NDC to
// directly interact with a state machine through messages
- NativeEvent event = new NativeEvent(code, raw);
+ NativeEvent event = new NativeEvent(code, raw, cooked);
mNsdStateMachine.sendMessage(NsdManager.NATIVE_DAEMON_EVENT, event);
return true;
}