Fixed HLS parsing of bad content IDs.

[ Merge of http://go/wvgerrit/207457 ]

When parsing Widevine's HLS key data, the key details are contained
in a data URI in the HLS X-KEY URI field.  The data of the URI is a
base64 encoded JSON object, containing the information required to
generate the license request.  The "content_id" field of the JSON
object is expected to be a base64 encoded; however, the HLS parser
did not verify that the decoding was successful.  In the event that
was not successful, the decoder would return an empty string, which
the parser would attempt to access the first element by reference
which may be a null reference.

In C++, creating a reference from a null point (without actually
accessing the value) is undefined; however most C++ implemenations
will not cause a segment fault; but it is not guarenteed by the
standard.

This change checks if the decoding was successful before attempting
to store the decoded "content_id" value.

A unit test is added to ensure that a parser fails gracefully.

Bug: 356210640
Test: HlsParseTest.BadHlsData_InvalidContentId
Change-Id: Ie2ad42d69953258659178dd1464d830b2723c6c7
This commit is contained in:
Alex Dale
2024-10-01 21:14:19 -07:00
parent 4ef3e2cee8
commit 380148e3e6
2 changed files with 30 additions and 7 deletions

View File

@@ -454,8 +454,7 @@ bool InitializationData::ConstructWidevineInitData(
LOGV("Base64 decode of json data failed");
return false;
}
std::string json_string((const char*)(&json_init_data[0]),
json_init_data.size());
const std::string json_string(json_init_data.begin(), json_init_data.end());
// Parse the Json string using jsmn
jsmn_parser parser;
@@ -513,12 +512,13 @@ bool InitializationData::ConstructWidevineInitData(
break;
case kContentIdState:
if (tokens[i].type == JSMN_STRING) {
std::string base64_content_id(json_string, tokens[i].start,
tokens[i].end - tokens[i].start);
std::vector<uint8_t> content_id_data =
const std::string base64_content_id = json_string.substr(
tokens[i].start, tokens[i].end - tokens[i].start);
const std::vector<uint8_t> content_id_data =
wvutil::Base64Decode(base64_content_id);
content_id.assign(reinterpret_cast<const char*>(&content_id_data[0]),
content_id_data.size());
if (!content_id_data.empty()) {
content_id.assign(content_id_data.begin(), content_id_data.end());
}
}
state = kParseState;
break;

View File

@@ -869,4 +869,27 @@ INSTANTIATE_TEST_SUITE_P(
HlsAttributeVariant(kHlsAttributeListInvalidIv, HLS_IV_ATTRIBUTE,
kHlsTestHexValueWithOddBytes, false)));
TEST_F(HlsParseTest, BadHlsData_InvalidContentId) {
std::ostringstream hls_uri_json_stream;
hls_uri_json_stream << "{";
hls_uri_json_stream << "\"provider\": \"HlsParseTest.BadHlsData\", ";
// Intentionally bad Base64 content ID.
hls_uri_json_stream << "\"content_id\": \"$$$$\", ";
hls_uri_json_stream << "\"key_ids\": [\"00000000000000000000000000000000\"]";
hls_uri_json_stream << "}";
const std::string hls_uri_json = hls_uri_json_stream.str();
std::ostringstream hls_stream;
hls_stream << "#EXT-X-KEY:";
hls_stream << "METHOD=AES-128,";
hls_stream << "URI=\"data:text/plain;base64,"
<< wvutil::Base64Encode(hls_uri_json) << "\",";
hls_stream << "IV=0x00000000000000000000000000000000,";
hls_stream << "KEYFORMAT=\"com.widevine\",";
hls_stream << "KEYFORMATVERSIONS=\"1\"";
const std::string hls_data = hls_stream.str();
// std::cout << "HLS Data:" << std::endl << hls_data << std::endl;
InitializationData init_data(HLS_INIT_DATA_FORMAT, hls_data);
EXPECT_TRUE(init_data.is_hls());
}
} // namespace wvcdm