已合并
社区漏洞fix #813
liuzongze创建于 6月23日
社区漏洞fix #813
已合并
共 7 个文件变更+324-22
| @@ -127,6 +127,21 @@ zchar Char::GetChar(const std::string &str, | |||
| 127 | unsigned int size = str.length(); | 127 | unsigned int size = str.length(); |
| 128 | unsigned int now = 0; | 128 | unsigned int now = 0; |
| 129 | while (*p && p < end) { | 129 | while (*p && p < end) { |
| 130 | + unsigned char firstByte = static_cast<unsigned char>(*p); | ||
| 131 | + unsigned int seqLen = BYTE_COUNT_1; | ||
| 132 | + if (firstByte >= 0xC0 && firstByte <= 0xDF) { | ||
| 133 | + seqLen = BYTE_COUNT_2; | ||
| 134 | + } else if (firstByte >= 0xE0 && firstByte <= 0xEF) { | ||
| 135 | + seqLen = BYTE_COUNT_3; | ||
| 136 | + } else if (firstByte >= 0xF0 && firstByte <= 0xF7) { | ||
| 137 | + seqLen = BYTE_COUNT_4; | ||
| 138 | + } else if (firstByte >= 0xF8) { | ||
| 139 | + break; | ||
| 140 | + } | ||
| 141 | + if (now + seqLen > size) { | ||
| 142 | + break; | ||
| 143 | + } | ||
| 144 | + | ||
| 130 | zchar unicode = GetCharInternal((unsigned char *)p, bsize); | 145 | zchar unicode = GetCharInternal((unsigned char *)p, bsize); |
| 131 | if (bsize == 0 || now + bsize > size) { | 146 | if (bsize == 0 || now + bsize > size) { |
| 132 | break; | 147 | break; |
| @@ -147,7 +162,7 @@ zchar Char::GetCharInternal(const unsigned char *cur, | |||
| 147 | unsigned int &size) | 162 | unsigned int &size) |
| 148 | { | 163 | { |
| 149 | if (isascii(*cur) != 0) { | 164 | if (isascii(*cur) != 0) { |
| 150 | - size = 1; | 165 | + size = BYTE_COUNT_1; |
| 151 | return *cur; | 166 | return *cur; |
| 152 | } | 167 | } |
| 153 | 168 | ||
| @@ -155,12 +170,12 @@ zchar Char::GetCharInternal(const unsigned char *cur, | |||
| 155 | zchar result = firstChar; | 170 | zchar result = firstChar; |
| 156 | zchar mask = 0x40; | 171 | zchar mask = 0x40; |
| 157 | zchar ignoreMask = 0xFFFFFF80; | 172 | zchar ignoreMask = 0xFFFFFF80; |
| 158 | - unsigned int num2Read = 1; | 173 | + unsigned int num2Read = BYTE_COUNT_1; |
| 159 | - for (; (firstChar & mask); num2Read++, ignoreMask |= mask, mask >>= 1) { | 174 | + for (; (firstChar & mask) && num2Read < BYTE_COUNT_4; num2Read++, ignoreMask |= mask, mask >>= 1) { |
| 160 | result = (result << BYTE_SHIFT) + (*cur++ & 0x3F); | 175 | result = (result << BYTE_SHIFT) + (*cur++ & 0x3F); |
| 161 | } | 176 | } |
| 162 | ignoreMask |= mask; | 177 | ignoreMask |= mask; |
| 163 | - result &= ~(ignoreMask << (BYTE_SHIFT * (num2Read - 1))); | 178 | + result &= ~(ignoreMask << (BYTE_SHIFT * (num2Read - BYTE_COUNT_1))); |
| 164 | size = num2Read; | 179 | size = num2Read; |
| 165 | return result; | 180 | return result; |
| 166 | } | 181 | } |
| @@ -74,7 +74,7 @@ public: | |||
| 74 | static constexpr char SIGNATURE = '['; | 74 | static constexpr char SIGNATURE = '['; |
| 75 | 75 | ||
| 76 | private: | 76 | private: |
| 77 | - static void ParseElement(IArray *array, /* [in] */ | 77 | + static bool ParseElement(IArray *array, /* [in] */ |
| 78 | std::function<sptr<IInterface>(std::string &)> func, /* [in] */ | 78 | std::function<sptr<IInterface>(std::string &)> func, /* [in] */ |
| 79 | const std::string &values, /* [in] */ | 79 | const std::string &values, /* [in] */ |
| 80 | long size); /* [in] */ | 80 | long size); /* [in] */ |
| @@ -99,7 +99,15 @@ bool Array::Equals(IObject &other) /* [in] */ | |||
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | for (long i = 0; i < size_; i++) { | 101 | for (long i = 0; i < size_; i++) { |
| 102 | - if (!Object::Equals(*(values_[i].GetRefPtr()), *(otherObj->values_[i].GetRefPtr()))) { | 102 | + auto *left = values_[i].GetRefPtr(); |
| 103 | + auto *right = otherObj->values_[i].GetRefPtr(); | ||
| 104 | + if (left == nullptr && right == nullptr) { | ||
| 105 | + continue; | ||
| 106 | + } | ||
| 107 | + if (left == nullptr || right == nullptr) { | ||
| 108 | + return false; | ||
| 109 | + } | ||
| 110 | + if (!Object::Equals(*left, *right)) { | ||
| 103 | return false; | 111 | return false; |
| 104 | } | 112 | } |
| 105 | } | 113 | } |
| @@ -154,7 +162,9 @@ sptr<IArray> Array::ParseString(const std::string &values, long size) | |||
| 154 | sptr<IArray> array = sptr<Array>::MakeSptr(size, g_IID_IString); | 162 | sptr<IArray> array = sptr<Array>::MakeSptr(size, g_IID_IString); |
| 155 | if (array != nullptr) { | 163 | if (array != nullptr) { |
| 156 | auto func = [](const std::string &str) -> sptr<IInterface> { return String::Parse(str); }; | 164 | auto func = [](const std::string &str) -> sptr<IInterface> { return String::Parse(str); }; |
| 157 | - ParseElement(array, func, values, size); | 165 | + if (!ParseElement(array, func, values, size)) { |
| 166 | + return nullptr; | ||
| 167 | + } | ||
| 158 | } | 168 | } |
| 159 | return array; | 169 | return array; |
| 160 | } | 170 | } |
| @@ -164,7 +174,9 @@ sptr<IArray> Array::ParseBoolean(const std::string &values, long size) | |||
| 164 | sptr<IArray> array = sptr<Array>::MakeSptr(size, g_IID_IBoolean); | 174 | sptr<IArray> array = sptr<Array>::MakeSptr(size, g_IID_IBoolean); |
| 165 | if (array != nullptr) { | 175 | if (array != nullptr) { |
| 166 | auto func = [](const std::string &str) -> sptr<IInterface> { return Boolean::Parse(str); }; | 176 | auto func = [](const std::string &str) -> sptr<IInterface> { return Boolean::Parse(str); }; |
| 167 | - ParseElement(array, func, values, size); | 177 | + if (!ParseElement(array, func, values, size)) { |
| 178 | + return nullptr; | ||
| 179 | + } | ||
| 168 | } | 180 | } |
| 169 | return array; | 181 | return array; |
| 170 | } | 182 | } |
| @@ -174,7 +186,9 @@ sptr<IArray> Array::ParseByte(const std::string &values, long size) | |||
| 174 | sptr<IArray> array = sptr<Array>::MakeSptr(size, g_IID_IByte); | 186 | sptr<IArray> array = sptr<Array>::MakeSptr(size, g_IID_IByte); |
| 175 | if (array != nullptr) { | 187 | if (array != nullptr) { |
| 176 | auto func = [](const std::string &str) -> sptr<IInterface> { return Byte::Parse(str); }; | 188 | auto func = [](const std::string &str) -> sptr<IInterface> { return Byte::Parse(str); }; |
| 177 | - ParseElement(array, func, values, size); | 189 | + if (!ParseElement(array, func, values, size)) { |
| 190 | + return nullptr; | ||
| 191 | + } | ||
| 178 | } | 192 | } |
| 179 | return array; | 193 | return array; |
| 180 | } | 194 | } |
| @@ -184,7 +198,9 @@ sptr<IArray> Array::ParseShort(const std::string &values, long size) | |||
| 184 | sptr<IArray> array = sptr<Array>::MakeSptr(size, g_IID_IShort); | 198 | sptr<IArray> array = sptr<Array>::MakeSptr(size, g_IID_IShort); |
| 185 | if (array != nullptr) { | 199 | if (array != nullptr) { |
| 186 | auto func = [](const std::string &str) -> sptr<IInterface> { return Short::Parse(str); }; | 200 | auto func = [](const std::string &str) -> sptr<IInterface> { return Short::Parse(str); }; |
| 187 | - ParseElement(array, func, values, size); | 201 | + if (!ParseElement(array, func, values, size)) { |
| 202 | + return nullptr; | ||
| 203 | + } | ||
| 188 | } | 204 | } |
| 189 | return array; | 205 | return array; |
| 190 | } | 206 | } |
| @@ -194,7 +210,9 @@ sptr<IArray> Array::ParseInteger(const std::string &values, long size) | |||
| 194 | sptr<IArray> array = sptr<Array>::MakeSptr(size, g_IID_IInteger); | 210 | sptr<IArray> array = sptr<Array>::MakeSptr(size, g_IID_IInteger); |
| 195 | if (array != nullptr) { | 211 | if (array != nullptr) { |
| 196 | auto func = [](const std::string &str) -> sptr<IInterface> { return Integer::Parse(str); }; | 212 | auto func = [](const std::string &str) -> sptr<IInterface> { return Integer::Parse(str); }; |
| 197 | - ParseElement(array, func, values, size); | 213 | + if (!ParseElement(array, func, values, size)) { |
| 214 | + return nullptr; | ||
| 215 | + } | ||
| 198 | } | 216 | } |
| 199 | return array; | 217 | return array; |
| 200 | } | 218 | } |
| @@ -204,7 +222,9 @@ sptr<IArray> Array::ParseLong(const std::string &values, long size) | |||
| 204 | sptr<IArray> array = sptr<Array>::MakeSptr(size, g_IID_ILong); | 222 | sptr<IArray> array = sptr<Array>::MakeSptr(size, g_IID_ILong); |
| 205 | if (array != nullptr) { | 223 | if (array != nullptr) { |
| 206 | auto func = [](const std::string &str) -> sptr<IInterface> { return Long::Parse(str); }; | 224 | auto func = [](const std::string &str) -> sptr<IInterface> { return Long::Parse(str); }; |
| 207 | - ParseElement(array, func, values, size); | 225 | + if (!ParseElement(array, func, values, size)) { |
| 226 | + return nullptr; | ||
| 227 | + } | ||
| 208 | } | 228 | } |
| 209 | return array; | 229 | return array; |
| 210 | } | 230 | } |
| @@ -214,7 +234,9 @@ sptr<IArray> Array::ParseFloat(const std::string &values, long size) | |||
| 214 | sptr<IArray> array = sptr<Array>::MakeSptr(size, g_IID_IFloat); | 234 | sptr<IArray> array = sptr<Array>::MakeSptr(size, g_IID_IFloat); |
| 215 | if (array != nullptr) { | 235 | if (array != nullptr) { |
| 216 | auto func = [](const std::string &str) -> sptr<IInterface> { return Float::Parse(str); }; | 236 | auto func = [](const std::string &str) -> sptr<IInterface> { return Float::Parse(str); }; |
| 217 | - ParseElement(array, func, values, size); | 237 | + if (!ParseElement(array, func, values, size)) { |
| 238 | + return nullptr; | ||
| 239 | + } | ||
| 218 | } | 240 | } |
| 219 | return array; | 241 | return array; |
| 220 | } | 242 | } |
| @@ -224,7 +246,9 @@ sptr<IArray> Array::ParseDouble(const std::string &values, long size) | |||
| 224 | sptr<IArray> array = sptr<Array>::MakeSptr(size, g_IID_IDouble); | 246 | sptr<IArray> array = sptr<Array>::MakeSptr(size, g_IID_IDouble); |
| 225 | if (array != nullptr) { | 247 | if (array != nullptr) { |
| 226 | auto func = [](const std::string &str) -> sptr<IInterface> { return Double::Parse(str); }; | 248 | auto func = [](const std::string &str) -> sptr<IInterface> { return Double::Parse(str); }; |
| 227 | - ParseElement(array, func, values, size); | 249 | + if (!ParseElement(array, func, values, size)) { |
| 250 | + return nullptr; | ||
| 251 | + } | ||
| 228 | } | 252 | } |
| 229 | return array; | 253 | return array; |
| 230 | } | 254 | } |
| @@ -233,7 +257,9 @@ sptr<IArray> Array::ParseChar(const std::string &values, long size) | |||
| 233 | sptr<IArray> array = sptr<Array>::MakeSptr(size, g_IID_IChar); | 257 | sptr<IArray> array = sptr<Array>::MakeSptr(size, g_IID_IChar); |
| 234 | if (array != nullptr) { | 258 | if (array != nullptr) { |
| 235 | auto func = [](const std::string &str) -> sptr<IInterface> { return Char::Parse(str); }; | 259 | auto func = [](const std::string &str) -> sptr<IInterface> { return Char::Parse(str); }; |
| 236 | - ParseElement(array, func, values, size); | 260 | + if (!ParseElement(array, func, values, size)) { |
| 261 | + return nullptr; | ||
| 262 | + } | ||
| 237 | } | 263 | } |
| 238 | return array; | 264 | return array; |
| 239 | } | 265 | } |
| @@ -242,7 +268,9 @@ sptr<IArray> Array::ParseArray(const std::string &values, long size) | |||
| 242 | sptr<IArray> array = sptr<Array>::MakeSptr(size, g_IID_IArray); | 268 | sptr<IArray> array = sptr<Array>::MakeSptr(size, g_IID_IArray); |
| 243 | if (array != nullptr) { | 269 | if (array != nullptr) { |
| 244 | auto func = [](const std::string &str) -> sptr<IInterface> { return Array::Parse(str); }; | 270 | auto func = [](const std::string &str) -> sptr<IInterface> { return Array::Parse(str); }; |
| 245 | - ParseElement(array, func, values, size); | 271 | + if (!ParseElement(array, func, values, size)) { |
| 272 | + return nullptr; | ||
| 273 | + } | ||
| 246 | } | 274 | } |
| 247 | return array; | 275 | return array; |
| 248 | } | 276 | } |
| @@ -252,7 +280,9 @@ sptr<IArray> Array::ParseWantParams(const std::string &values, long size) | |||
| 252 | sptr<IArray> array = sptr<Array>::MakeSptr(size, g_IID_IWantParams); | 280 | sptr<IArray> array = sptr<Array>::MakeSptr(size, g_IID_IWantParams); |
| 253 | if (array != nullptr) { | 281 | if (array != nullptr) { |
| 254 | auto func = [](const std::string &str) -> sptr<IInterface> { return WantParamWrapper::Parse(str); }; | 282 | auto func = [](const std::string &str) -> sptr<IInterface> { return WantParamWrapper::Parse(str); }; |
| 255 | - ParseElement(array, func, values, size); | 283 | + if (!ParseElement(array, func, values, size)) { |
| 284 | + return nullptr; | ||
| 285 | + } | ||
| 256 | } | 286 | } |
| 257 | return array; | 287 | return array; |
| 258 | } | 288 | } |
| @@ -314,13 +344,13 @@ sptr<IArray> Array::Parse(const std::string &arrayStr) /* [in] */ | |||
| 314 | return nullptr; | 344 | return nullptr; |
| 315 | } | 345 | } |
| 316 | 346 | ||
| 317 | -void Array::ParseElement(IArray *array, /* [in] */ | 347 | +bool Array::ParseElement(IArray *array, /* [in] */ |
| 318 | std::function<sptr<IInterface>(std::string &)> func, /* [in] */ | 348 | std::function<sptr<IInterface>(std::string &)> func, /* [in] */ |
| 319 | const std::string &values, /* [in] */ | 349 | const std::string &values, /* [in] */ |
| 320 | long size) /* [in] */ | 350 | long size) /* [in] */ |
| 321 | { | 351 | { |
| 322 | if (array == nullptr) { | 352 | if (array == nullptr) { |
| 323 | - return; | 353 | + return false; |
| 324 | } | 354 | } |
| 325 | 355 | ||
| 326 | std::size_t beginIdx = 0; | 356 | std::size_t beginIdx = 0; |
| @@ -338,8 +368,13 @@ void Array::ParseElement(IArray *array, /* [in] */ | |||
| 338 | } else { | 368 | } else { |
| 339 | valueStr = values.substr(beginIdx, values.length() - beginIdx); | 369 | valueStr = values.substr(beginIdx, values.length() - beginIdx); |
| 340 | } | 370 | } |
| 341 | - array->Set(i, func(valueStr)); | 371 | + auto element = func(valueStr); |
| 372 | + if (element == nullptr) { | ||
| 373 | + return false; | ||
| 374 | + } | ||
| 375 | + array->Set(i, element); | ||
| 342 | } | 376 | } |
| 377 | + return true; | ||
| 343 | } | 378 | } |
| 344 | 379 | ||
| 345 | bool Array::IsBooleanArray(IArray *array) /* [in] */ | 380 | bool Array::IsBooleanArray(IArray *array) /* [in] */ |
| @@ -223,5 +223,41 @@ HWTEST_F(AAfWKZcharWrapperTest, ZcharWrapperTest_GetCharInternal_001, TestSize.L | |||
| 223 | zcharValue.GetCharInternal(cur, size); | 223 | zcharValue.GetCharInternal(cur, size); |
| 224 | EXPECT_EQ(3, size); | 224 | EXPECT_EQ(3, size); |
| 225 | } | 225 | } |
| 226 | + | ||
| 227 | +/** | ||
| 228 | + * @tc.number: ZcharWrapperTest_GetCharInternal_002 | ||
| 229 | + * @tc.name: GetCharInternal | ||
| 230 | + * @tc.desc: Verify GetCharInternal caps num2Read at 4 for invalid leading byte 0xFF. | ||
| 231 | + * Without the cap, 0xFF would trigger 7 continuation byte reads (OOB + UB shift). | ||
| 232 | + */ | ||
| 233 | +HWTEST_F(AAfWKZcharWrapperTest, ZcharWrapperTest_GetCharInternal_002, TestSize.Level1) | ||
| 234 | +{ | ||
| 235 | + zchar value = 0; | ||
| 236 | + Char zcharValue(value); | ||
| 237 | + // 0xFF is never valid in UTF-8. The num2Read < 4 cap limits continuation reads to 3. | ||
| 238 | + unsigned char buf[4] = {0xFF, 0x80, 0x80, 0x80}; | ||
| 239 | + unsigned int size = 0; | ||
| 240 | + zcharValue.GetCharInternal(buf, size); | ||
| 241 | + // With cap: size is 4 (not 8). Without cap: undefined behavior (shift > 31 bits). | ||
| 242 | + EXPECT_EQ(4, size); | ||
| 243 | +} | ||
| 244 | + | ||
| 245 | +/** | ||
| 246 | + * @tc.number: ZcharWrapperTest_GetCharInternal_003 | ||
| 247 | + * @tc.name: GetCharInternal | ||
| 248 | + * @tc.desc: Verify GetCharInternal correctly decodes a valid 4-byte UTF-8 sequence | ||
| 249 | + * (U+1F600 😀 = F0 9F 98 80). | ||
| 250 | + */ | ||
| 251 | +HWTEST_F(AAfWKZcharWrapperTest, ZcharWrapperTest_GetCharInternal_003, TestSize.Level1) | ||
| 252 | +{ | ||
| 253 | + zchar value = 0; | ||
| 254 | + Char zcharValue(value); | ||
| 255 | + // U+1F600 😀 in UTF-8: F0 9F 98 80 | ||
| 256 | + unsigned char buf[4] = {0xF0, 0x9F, 0x98, 0x80}; | ||
| 257 | + unsigned int size = 0; | ||
| 258 | + zchar result = zcharValue.GetCharInternal(buf, size); | ||
| 259 | + EXPECT_EQ(4, size); | ||
| 260 | + EXPECT_EQ(static_cast<zchar>(0x1F600), result); | ||
| 261 | +} | ||
| 226 | } | 262 | } |
| 227 | } | 263 | } |
| @@ -412,14 +412,14 @@ HWTEST_F(ArrayWrapperBaseTest, AaFwk_Array_Wrapper_Parse_0100, Function | Medium | |||
| 412 | EXPECT_EQ(arrFunction("{Test}"), nullptr); | 412 | EXPECT_EQ(arrFunction("{Test}"), nullptr); |
| 413 | EXPECT_NE(arrFunction("C3{1,2,3}"), nullptr); | 413 | EXPECT_NE(arrFunction("C3{1,2,3}"), nullptr); |
| 414 | EXPECT_NE(arrFunction("T3{1,2,3}"), nullptr); | 414 | EXPECT_NE(arrFunction("T3{1,2,3}"), nullptr); |
| 415 | - EXPECT_NE(arrFunction("Z3{1,2,3}"), nullptr); | 415 | + EXPECT_EQ(arrFunction("Z3{1,2,3}"), nullptr); |
| 416 | EXPECT_NE(arrFunction("B3{1,2,3}"), nullptr); | 416 | EXPECT_NE(arrFunction("B3{1,2,3}"), nullptr); |
| 417 | EXPECT_NE(arrFunction("S3{1,2,3}"), nullptr); | 417 | EXPECT_NE(arrFunction("S3{1,2,3}"), nullptr); |
| 418 | EXPECT_NE(arrFunction("I3{1,2,3}"), nullptr); | 418 | EXPECT_NE(arrFunction("I3{1,2,3}"), nullptr); |
| 419 | EXPECT_NE(arrFunction("J3{1,2,3}"), nullptr); | 419 | EXPECT_NE(arrFunction("J3{1,2,3}"), nullptr); |
| 420 | EXPECT_NE(arrFunction("F3{1,2,3}"), nullptr); | 420 | EXPECT_NE(arrFunction("F3{1,2,3}"), nullptr); |
| 421 | EXPECT_NE(arrFunction("D3{1,2,3}"), nullptr); | 421 | EXPECT_NE(arrFunction("D3{1,2,3}"), nullptr); |
| 422 | - EXPECT_NE(arrFunction("[3{1,2,3}"), nullptr); | 422 | + EXPECT_EQ(arrFunction("[3{1,2,3}"), nullptr); |
| 423 | EXPECT_NE(arrFunction("W3{1,2,3}"), nullptr); | 423 | EXPECT_NE(arrFunction("W3{1,2,3}"), nullptr); |
| 424 | } | 424 | } |
| 425 | } | 425 | } |
| @@ -926,6 +926,53 @@ HWTEST_F(WantParamsBaseTest, AaFwk_WantParams_CompareInterface_1002, Function | | |||
| 926 | EXPECT_TRUE(result); | 926 | EXPECT_TRUE(result); |
| 927 | } | 927 | } |
| 928 | 928 | ||
| 929 | +/** | ||
| 930 | + * @tc.number: AaFwk_WantParams_GetInterfaceByType_InvalidArray_0100 | ||
| 931 | + * @tc.name: GetInterfaceByType | ||
| 932 | + * @tc.desc: Verify GetInterfaceByType returns nullptr when array parsing fails | ||
| 933 | + * due to an invalid element that ParseElement rejects. | ||
| 934 | + */ | ||
| 935 | +HWTEST_F(WantParamsBaseTest, AaFwk_WantParams_GetInterfaceByType_InvalidArray_0100, Function | MediumTest | Level1) | ||
| 936 | +{ | ||
| 937 | + // "Z3{true,maybe,false}" — "maybe" is not a valid Boolean. | ||
| 938 | + // Boolean::Parse("maybe") returns nullptr, ParseElement detects this, | ||
| 939 | + // ParseBoolean returns nullptr, Array::Parse returns nullptr. | ||
| 940 | + const std::string value = "Z3{true,maybe,false}"; | ||
| 941 | + sptr<IInterface> result = WantParams::GetInterfaceByType(WantParams::VALUE_TYPE_ARRAY, value); | ||
| 942 | + EXPECT_TRUE(result == nullptr); | ||
| 943 | +} | ||
| 944 | + | ||
| 945 | +/** | ||
| 946 | + * @tc.number: AaFwk_WantParams_GetInterfaceByType_InvalidArray_0200 | ||
| 947 | + * @tc.name: GetInterfaceByType | ||
| 948 | + * @tc.desc: Verify GetInterfaceByType returns nullptr for an integer array | ||
| 949 | + * containing a non-integer element. | ||
| 950 | + */ | ||
| 951 | +HWTEST_F(WantParamsBaseTest, AaFwk_WantParams_GetInterfaceByType_InvalidArray_0200, Function | MediumTest | Level1) | ||
| 952 | +{ | ||
| 953 | + // "I3{2,abc,4}" — "abc" is not a valid integer. | ||
| 954 | + const std::string value = "I3{2,abc,4}"; | ||
| 955 | + sptr<IInterface> result = WantParams::GetInterfaceByType(WantParams::VALUE_TYPE_ARRAY, value); | ||
| 956 | + EXPECT_TRUE(result == nullptr); | ||
| 957 | +} | ||
| 958 | + | ||
| 959 | +/** | ||
| 960 | + * @tc.number: AaFwk_WantParams_CompareInterface_InvalidArray_0100 | ||
| 961 | + * @tc.name: CompareInterface | ||
| 962 | + * @tc.desc: Verify CompareInterface returns false when both interfaces are nullptr | ||
| 963 | + * (GetInterfaceByType returns nullptr for invalid array, type checks fail). | ||
| 964 | + */ | ||
| 965 | +HWTEST_F(WantParamsBaseTest, AaFwk_WantParams_CompareInterface_InvalidArray_0100, Function | MediumTest | Level1) | ||
| 966 | +{ | ||
| 967 | + // Both elements fail to parse → both are nullptr → GetDataType returns VALUE_TYPE_NULL | ||
| 968 | + // VALUE_TYPE_NULL != VALUE_TYPE_ARRAY → CompareInterface returns false | ||
| 969 | + const std::string value = "Z3{true,maybe,false}"; | ||
| 970 | + sptr<IInterface> iObj1 = WantParams::GetInterfaceByType(WantParams::VALUE_TYPE_ARRAY, value); | ||
| 971 | + sptr<IInterface> iObj2 = WantParams::GetInterfaceByType(WantParams::VALUE_TYPE_ARRAY, value); | ||
| 972 | + bool result = WantParams::CompareInterface(iObj1, iObj2, WantParams::VALUE_TYPE_ARRAY); | ||
| 973 | + EXPECT_FALSE(result); | ||
| 974 | +} | ||
| 975 | + | ||
| 929 | /** | 976 | /** |
| 930 | * @tc.number: AaFwk_WantParams_WriteArrayToParcelString_0100 | 977 | * @tc.number: AaFwk_WantParams_WriteArrayToParcelString_0100 |
| 931 | * @tc.name: WriteArrayToParcelString | 978 | * @tc.name: WriteArrayToParcelString |
| @@ -22,6 +22,7 @@ | |||
| 22 | 22 | ||
| 23 | 23 | ||
| 24 | 24 | ||
| 25 | + | ||
| 25 | 26 | ||
| 26 | 27 | ||
| 27 | 28 | ||
| @@ -4046,6 +4047,174 @@ HWTEST_F(WantBaseTest, array_test_006, TestSize.Level1) | |||
| 4046 | EXPECT_EQ(arrayObj->ToString(), std::string("I5{}")); | 4047 | EXPECT_EQ(arrayObj->ToString(), std::string("I5{}")); |
| 4047 | } | 4048 | } |
| 4048 | 4049 | ||
| 4050 | +/* | ||
| 4051 | + * Feature: Array | ||
| 4052 | + * Function: Parse | ||
| 4053 | + * SubFunction: NA | ||
| 4054 | + * FunctionPoints: ParseElement rejects null from Boolean::Parse callback | ||
| 4055 | + * EnvConditions: NA | ||
| 4056 | + * CaseDescription: Verify Parse returns nullptr when a Boolean element fails to parse. | ||
| 4057 | + */ | ||
| 4058 | +HWTEST_F(WantBaseTest, array_test_007, TestSize.Level1) | ||
| 4059 | +{ | ||
| 4060 | + // "maybe" is not a valid Boolean, Boolean::Parse returns nullptr, | ||
| 4061 | + // ParseElement detects this and returns false, ParseBoolean propagates nullptr. | ||
| 4062 | + sptr<IArray> arrayObj = Array::Parse("Z3{true,maybe,false}"); | ||
| 4063 | + EXPECT_TRUE(arrayObj == nullptr); | ||
| 4064 | +} | ||
| 4065 | + | ||
| 4066 | +/* | ||
| 4067 | + * Feature: Array | ||
| 4068 | + * Function: Parse | ||
| 4069 | + * SubFunction: NA | ||
| 4070 | + * FunctionPoints: ParseElement rejects null from Integer::Parse callback | ||
| 4071 | + * EnvConditions: NA | ||
| 4072 | + * CaseDescription: Verify Parse returns nullptr when an Integer element fails to parse. | ||
| 4073 | + */ | ||
| 4074 | +HWTEST_F(WantBaseTest, array_test_008, TestSize.Level1) | ||
| 4075 | +{ | ||
| 4076 | + // "abc" is not a valid integer, Integer::Parse returns nullptr, | ||
| 4077 | + // ParseElement detects this and returns false, ParseInteger propagates nullptr. | ||
| 4078 | + sptr<IArray> arrayObj = Array::Parse("I3{2,abc,4}"); | ||
| 4079 | + EXPECT_TRUE(arrayObj == nullptr); | ||
| 4080 | +} | ||
| 4081 | + | ||
| 4082 | +/* | ||
| 4083 | + * Feature: Array | ||
| 4084 | + * Function: Parse | ||
| 4085 | + * SubFunction: NA | ||
| 4086 | + * FunctionPoints: ParseElement rejects null from Float::Parse callback | ||
| 4087 | + * EnvConditions: NA | ||
| 4088 | + * CaseDescription: Verify Parse returns nullptr when a Float element fails to parse. | ||
| 4089 | + */ | ||
| 4090 | +HWTEST_F(WantBaseTest, array_test_009, TestSize.Level1) | ||
| 4091 | +{ | ||
| 4092 | + // "notanum" is not a valid float, Float::Parse returns nullptr, | ||
| 4093 | + // ParseElement detects this and returns false, ParseFloat propagates nullptr. | ||
| 4094 | + sptr<IArray> arrayObj = Array::Parse("F3{1.5,notanum,3.0}"); | ||
| 4095 | + EXPECT_TRUE(arrayObj == nullptr); | ||
| 4096 | +} | ||
| 4097 | + | ||
| 4098 | +/* | ||
| 4099 | + * Feature: Array | ||
| 4100 | + * Function: Parse | ||
| 4101 | + * SubFunction: NA | ||
| 4102 | + * FunctionPoints: ParseElement rejects null from Byte::Parse callback | ||
| 4103 | + * EnvConditions: NA | ||
| 4104 | + * CaseDescription: Verify Parse returns nullptr when a Byte element fails to parse. | ||
| 4105 | + */ | ||
| 4106 | +HWTEST_F(WantBaseTest, array_test_010, TestSize.Level1) | ||
| 4107 | +{ | ||
| 4108 | + // "" (empty string) is not a valid byte, Byte::Parse returns nullptr, | ||
| 4109 | + // ParseElement detects this and returns false, ParseByte propagates nullptr. | ||
| 4110 | + sptr<IArray> arrayObj = Array::Parse("B3{1,,3}"); | ||
| 4111 | + EXPECT_TRUE(arrayObj == nullptr); | ||
| 4112 | +} | ||
| 4113 | + | ||
| 4114 | +/* | ||
| 4115 | + * Feature: Array | ||
| 4116 | + * Function: Equals | ||
| 4117 | + * SubFunction: NA | ||
| 4118 | + * FunctionPoints: Equals with null elements (defense-in-depth) | ||
| 4119 | + * EnvConditions: NA | ||
| 4120 | + * CaseDescription: Verify Equals treats both-null elements as equal (no crash). | ||
| 4121 | + */ | ||
| 4122 | +HWTEST_F(WantBaseTest, array_test_011, TestSize.Level1) | ||
| 4123 | +{ | ||
| 4124 | + // Two arrays where the same index is null (unset) in both: | ||
| 4125 | + // null == null → continue (treated as equal) | ||
| 4126 | + sptr<IArray> arrayObj1 = new Array(2, g_IID_IInteger); | ||
| 4127 | + arrayObj1->Set(0, Integer::Box(1)); | ||
| 4128 | + // arrayObj1 index 1 is still nullptr (unset) | ||
| 4129 | + | ||
| 4130 | + sptr<IArray> arrayObj2 = new Array(2, g_IID_IInteger); | ||
| 4131 | + arrayObj2->Set(0, Integer::Box(1)); | ||
| 4132 | + // arrayObj2 index 1 is still nullptr (unset) | ||
| 4133 | + | ||
| 4134 | + EXPECT_TRUE(Object::Equals(*(arrayObj1.GetRefPtr()), *(arrayObj2.GetRefPtr()))); | ||
| 4135 | +} | ||
| 4136 | + | ||
| 4137 | +/* | ||
| 4138 | + * Feature: Array | ||
| 4139 | + * Function: Equals | ||
| 4140 | + * SubFunction: NA | ||
| 4141 | + * FunctionPoints: Equals with null vs non-null elements (defense-in-depth) | ||
| 4142 | + * EnvConditions: NA | ||
| 4143 | + * CaseDescription: Verify Equals handles null vs non-null safely — not equal, no crash. | ||
| 4144 | + */ | ||
| 4145 | +HWTEST_F(WantBaseTest, array_test_012, TestSize.Level1) | ||
| 4146 | +{ | ||
| 4147 | + // One array has an element set, the other has nullptr at same index: | ||
| 4148 | + // null != value → return false | ||
| 4149 | + sptr<IArray> arrayObj1 = new Array(2, g_IID_IInteger); | ||
| 4150 | + arrayObj1->Set(0, Integer::Box(1)); | ||
| 4151 | + arrayObj1->Set(1, Integer::Box(2)); | ||
| 4152 | + | ||
| 4153 | + sptr<IArray> arrayObj2 = new Array(2, g_IID_IInteger); | ||
| 4154 | + arrayObj2->Set(0, Integer::Box(1)); | ||
| 4155 | + // arrayObj2 index 1 is nullptr (unset) | ||
| 4156 | + | ||
| 4157 | + EXPECT_FALSE(Object::Equals(*(arrayObj1.GetRefPtr()), *(arrayObj2.GetRefPtr()))); | ||
| 4158 | +} | ||
| 4159 | + | ||
| 4160 | +/* | ||
| 4161 | + * Feature: Array | ||
| 4162 | + * Function: Parse | ||
| 4163 | + * SubFunction: NA | ||
| 4164 | + * FunctionPoints: ParseElement with valid Boolean array still succeeds | ||
| 4165 | + * EnvConditions: NA | ||
| 4166 | + * CaseDescription: Verify a fully valid Boolean array still parses correctly after fix. | ||
| 4167 | + */ | ||
| 4168 | +HWTEST_F(WantBaseTest, array_test_013, TestSize.Level1) | ||
| 4169 | +{ | ||
| 4170 | + sptr<IArray> arrayObj = Array::Parse("Z3{true,false,true}"); | ||
| 4171 | + EXPECT_TRUE(arrayObj != nullptr); | ||
| 4172 | + sptr<IInterface> valueObj; | ||
| 4173 | + arrayObj->Get(0, valueObj); | ||
| 4174 | + EXPECT_EQ(Boolean::Unbox(IBoolean::Query(valueObj)), true); | ||
| 4175 | + arrayObj->Get(1, valueObj); | ||
| 4176 | + EXPECT_EQ(Boolean::Unbox(IBoolean::Query(valueObj)), false); | ||
| 4177 | + arrayObj->Get(2, valueObj); | ||
| 4178 | + EXPECT_EQ(Boolean::Unbox(IBoolean::Query(valueObj)), true); | ||
| 4179 | +} | ||
| 4180 | + | ||
| 4181 | +/* | ||
| 4182 | + * Feature: Array | ||
| 4183 | + * Function: Parse | ||
| 4184 | + * SubFunction: NA | ||
| 4185 | + * FunctionPoints: ParseElement with valid Char array still succeeds | ||
| 4186 | + * EnvConditions: NA | ||
| 4187 | + * CaseDescription: Verify Char array (never returns null from callback) still parses correctly. | ||
| 4188 | + */ | ||
| 4189 | +HWTEST_F(WantBaseTest, array_test_014, TestSize.Level1) | ||
| 4190 | +{ | ||
| 4191 | + sptr<IArray> arrayObj = Array::Parse("C3{a,b,c}"); | ||
| 4192 | + EXPECT_TRUE(arrayObj != nullptr); | ||
| 4193 | + sptr<IInterface> valueObj; | ||
| 4194 | + arrayObj->Get(0, valueObj); | ||
| 4195 | + EXPECT_EQ(Char::Unbox(IChar::Query(valueObj)), U'a'); | ||
| 4196 | + arrayObj->Get(1, valueObj); | ||
| 4197 | + EXPECT_EQ(Char::Unbox(IChar::Query(valueObj)), U'b'); | ||
| 4198 | + arrayObj->Get(2, valueObj); | ||
| 4199 | + EXPECT_EQ(Char::Unbox(IChar::Query(valueObj)), U'c'); | ||
| 4200 | +} | ||
| 4201 | + | ||
| 4202 | +/* | ||
| 4203 | + * Feature: Array | ||
| 4204 | + * Function: Parse | ||
| 4205 | + * SubFunction: NA | ||
| 4206 | + * FunctionPoints: Parse with empty values string returns nullptr | ||
| 4207 | + * EnvConditions: NA | ||
| 4208 | + * CaseDescription: Verify an array with empty values string fails to parse | ||
| 4209 | + * (empty string is an invalid element for all numeric/boolean types). | ||
| 4210 | + */ | ||
| 4211 | +HWTEST_F(WantBaseTest, array_test_015, TestSize.Level1) | ||
| 4212 | +{ | ||
| 4213 | + // size=1 but values string is empty | ||
| 4214 | + sptr<IArray> arrayObj = Array::Parse("I1{}"); | ||
| 4215 | + EXPECT_TRUE(arrayObj == nullptr); | ||
| 4216 | +} | ||
| 4217 | + | ||
| 4049 | /** | 4218 | /** |
| 4050 | * @tc.number: DumpInfo_test_001 | 4219 | * @tc.number: DumpInfo_test_001 |
| 4051 | * @tc.name: DumpInfo | 4220 | * @tc.name: DumpInfo |
TDD已通过