summaryrefslogtreecommitdiffstats
path: root/media/jni/android_media_MediaScanner.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'media/jni/android_media_MediaScanner.cpp')
-rw-r--r--media/jni/android_media_MediaScanner.cpp64
1 files changed, 63 insertions, 1 deletions
diff --git a/media/jni/android_media_MediaScanner.cpp b/media/jni/android_media_MediaScanner.cpp
index b88296f..09152f5 100644
--- a/media/jni/android_media_MediaScanner.cpp
+++ b/media/jni/android_media_MediaScanner.cpp
@@ -56,6 +56,53 @@ static status_t checkAndClearExceptionFromCallback(JNIEnv* env, const char* meth
return OK;
}
+// stolen from dalvik/vm/checkJni.cpp
+static bool isValidUtf8(const char* bytes) {
+ while (*bytes != '\0') {
+ unsigned char utf8 = *(bytes++);
+ // Switch on the high four bits.
+ switch (utf8 >> 4) {
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ case 0x07:
+ // Bit pattern 0xxx. No need for any extra bytes.
+ break;
+ case 0x08:
+ case 0x09:
+ case 0x0a:
+ case 0x0b:
+ case 0x0f:
+ /*
+ * Bit pattern 10xx or 1111, which are illegal start bytes.
+ * Note: 1111 is valid for normal UTF-8, but not the
+ * modified UTF-8 used here.
+ */
+ return false;
+ case 0x0e:
+ // Bit pattern 1110, so there are two additional bytes.
+ utf8 = *(bytes++);
+ if ((utf8 & 0xc0) != 0x80) {
+ return false;
+ }
+ // Fall through to take care of the final byte.
+ case 0x0c:
+ case 0x0d:
+ // Bit pattern 110x, so there is one additional byte.
+ utf8 = *(bytes++);
+ if ((utf8 & 0xc0) != 0x80) {
+ return false;
+ }
+ break;
+ }
+ }
+ return true;
+}
+
class MyMediaScannerClient : public MediaScannerClient
{
public:
@@ -123,7 +170,22 @@ public:
mEnv->ExceptionClear();
return NO_MEMORY;
}
- if ((valueStr = mEnv->NewStringUTF(value)) == NULL) {
+ char *cleaned = NULL;
+ if (!isValidUtf8(value)) {
+ cleaned = strdup(value);
+ char *chp = cleaned;
+ char ch;
+ while ((ch = *chp)) {
+ if (ch & 0x80) {
+ *chp = '?';
+ }
+ chp++;
+ }
+ value = cleaned;
+ }
+ valueStr = mEnv->NewStringUTF(value);
+ free(cleaned);
+ if (valueStr == NULL) {
mEnv->DeleteLocalRef(nameStr);
mEnv->ExceptionClear();
return NO_MEMORY;