Only allow UTF8 encoded property values

Java already restricts properties to only UTF8 valid strings, and
this change makes this restriction also apply to all native code.

Bug: 63177684
Test: new unit tests
Change-Id: I9fa0ecc0da066b0a026db3497c0f0cbf3f5c2d5a
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 223d34e..1a44fe3 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -33,6 +33,7 @@
 #include <sys/types.h>
 #include <sys/un.h>
 #include <unistd.h>
+#include <wchar.h>
 
 #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
 #include <sys/_system_properties.h>
@@ -160,6 +161,12 @@
         return PROP_ERROR_INVALID_VALUE;
     }
 
+    if (mbstowcs(nullptr, value.data(), 0) == static_cast<std::size_t>(-1)) {
+        LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: "
+                   << "value not a UTF8 encoded string";
+        return PROP_ERROR_INVALID_VALUE;
+    }
+
     prop_info* pi = (prop_info*) __system_property_find(name.c_str());
     if (pi != nullptr) {
         // ro.* properties are actually "write-once".
diff --git a/init/property_service_test.cpp b/init/property_service_test.cpp
index 3a64e02..95dd340 100644
--- a/init/property_service_test.cpp
+++ b/init/property_service_test.cpp
@@ -21,8 +21,11 @@
 #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
 #include <sys/_system_properties.h>
 
+#include <android-base/properties.h>
 #include <gtest/gtest.h>
 
+using android::base::SetProperty;
+
 namespace android {
 namespace init {
 
@@ -50,5 +53,19 @@
   ASSERT_EQ(0, close(fd));
 }
 
+TEST(property_service, non_utf8_value) {
+    ASSERT_TRUE(SetProperty("property_service_utf8_test", "base_success"));
+    EXPECT_FALSE(SetProperty("property_service_utf8_test", "\x80"));
+    EXPECT_FALSE(SetProperty("property_service_utf8_test", "\xC2\x01"));
+    EXPECT_FALSE(SetProperty("property_service_utf8_test", "\xE0\xFF"));
+    EXPECT_FALSE(SetProperty("property_service_utf8_test", "\xE0\xA0\xFF"));
+    EXPECT_FALSE(SetProperty("property_service_utf8_test", "\xF0\x01\xFF"));
+    EXPECT_FALSE(SetProperty("property_service_utf8_test", "\xF0\x90\xFF"));
+    EXPECT_FALSE(SetProperty("property_service_utf8_test", "\xF0\x90\x80\xFF"));
+    EXPECT_FALSE(SetProperty("property_service_utf8_test", "\xF0\x90\x80"));
+    EXPECT_FALSE(SetProperty("property_service_utf8_test", "ab\xF0\x90\x80\x80qe\xF0\x90\x80"));
+    EXPECT_TRUE(SetProperty("property_service_utf8_test", "\xF0\x90\x80\x80"));
+}
+
 }  // namespace init
 }  // namespace android