From 6ba96555aeaad66fc1a0156f13275b7052d8ab6a Mon Sep 17 00:00:00 2001 From: Lazar Kovacic Date: Sat, 3 Aug 2024 02:10:01 +0200 Subject: [PATCH] TV App: Add validation logic for supported clusters and response commands (#34454) * Add validation logic * Restyled by google-java-format * Restyled by clang-format --------- Co-authored-by: Restyled.io --- .../matter/tv/server/utils/ResourceUtils.java | 67 ++++++++++--------- .../java/ContentAppCommandDelegate.cpp | 39 +++++++++++ 2 files changed, 75 insertions(+), 31 deletions(-) diff --git a/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/utils/ResourceUtils.java b/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/utils/ResourceUtils.java index 1a04c5294d2f30..f0feb70d529677 100644 --- a/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/utils/ResourceUtils.java +++ b/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/utils/ResourceUtils.java @@ -58,38 +58,43 @@ public Set getSupportedClusters(final Resources resources, fin SupportedCluster cluster = new SupportedCluster(); while (reader.hasNext()) { String name = reader.nextName(); - if (name.equals(KEY_CLUSTER_ID)) { - cluster.clusterIdentifier = reader.nextInt(); - } else if (name.equals(KEY_FEATURE_FLAGS)) { - cluster.features = reader.nextInt(); - } else if (name.equals(KEY_OPTIONAL_COMMANDS)) { - List commands = new ArrayList<>(); - reader.beginArray(); - while (reader.hasNext()) { - commands.add(reader.nextInt()); + try { + if (name.equals(KEY_CLUSTER_ID)) { + cluster.clusterIdentifier = reader.nextInt(); + } else if (name.equals(KEY_FEATURE_FLAGS)) { + cluster.features = reader.nextInt(); + } else if (name.equals(KEY_OPTIONAL_COMMANDS)) { + List commands = new ArrayList<>(); + reader.beginArray(); + while (reader.hasNext()) { + commands.add(reader.nextInt()); + } + reader.endArray(); + int[] commandIds = new int[commands.size()]; + int i = 0; + for (Integer command : commands) { + commandIds[i++] = command; + } + cluster.optionalCommandIdentifiers = commandIds; + } else if (name.equals(KEY_OPTIONAL_ATTRIBUTES)) { + List attributes = new ArrayList<>(); + reader.beginArray(); + while (reader.hasNext()) { + attributes.add(reader.nextInt()); + } + reader.endArray(); + int[] attributeIds = new int[attributes.size()]; + int i = 0; + for (Integer command : attributes) { + attributeIds[i++] = command; + } + cluster.optionalAttributesIdentifiers = attributeIds; + } else { + reader.skipValue(); } - reader.endArray(); - int[] commandIds = new int[commands.size()]; - int i = 0; - for (Integer command : commands) { - commandIds[i++] = command; - } - cluster.optionalCommandIdentifiers = commandIds; - } else if (name.equals(KEY_OPTIONAL_ATTRIBUTES)) { - List attributes = new ArrayList<>(); - reader.beginArray(); - while (reader.hasNext()) { - attributes.add(reader.nextInt()); - } - reader.endArray(); - int[] attributeIds = new int[attributes.size()]; - int i = 0; - for (Integer command : attributes) { - attributeIds[i++] = command; - } - cluster.optionalAttributesIdentifiers = attributeIds; - } else { - reader.skipValue(); + } catch (NumberFormatException | IllegalStateException e) { + Log.e(TAG, "Invalid number format in JSON for key: " + name, e); + reader.skipValue(); // Skip the invalid entry } } supportedClusters.add(cluster); diff --git a/examples/tv-app/android/java/ContentAppCommandDelegate.cpp b/examples/tv-app/android/java/ContentAppCommandDelegate.cpp index 199ec7761be0c8..8d459588a7a8d6 100644 --- a/examples/tv-app/android/java/ContentAppCommandDelegate.cpp +++ b/examples/tv-app/android/java/ContentAppCommandDelegate.cpp @@ -133,6 +133,26 @@ Status ContentAppCommandDelegate::InvokeCommand(EndpointId epId, ClusterId clust JniUtfString respStr(env, resp); ChipLogProgress(Zcl, "ContentAppCommandDelegate::InvokeCommand got response %s", respStr.c_str()); + Json::CharReaderBuilder readerBuilder; + std::string errors; + + std::unique_ptr testReader(readerBuilder.newCharReader()); + + if (!testReader->parse(respStr.c_str(), respStr.c_str() + std::strlen(respStr.c_str()), &value, &errors)) + { + ChipLogError(Zcl, "Failed to parse JSON: %s\n", errors.c_str()); + env->DeleteLocalRef(resp); + return chip::Protocols::InteractionModel::Status::Failure; + } + + // Validate and access JSON data safely + if (!value.isObject()) + { + ChipLogError(Zcl, "Invalid JSON structure: not an object"); + env->DeleteLocalRef(resp); + return chip::Protocols::InteractionModel::Status::Failure; + } + Json::Reader reader; if (!reader.parse(respStr.c_str(), value)) { @@ -166,7 +186,26 @@ void ContentAppCommandDelegate::FormatResponseData(CommandHandlerInterface::Hand { handlerContext.SetCommandHandled(); Json::Reader reader; + + Json::CharReaderBuilder readerBuilder; + std::string errors; + Json::Value value; + std::unique_ptr testReader(readerBuilder.newCharReader()); + + if (!testReader->parse(response, response + std::strlen(response), &value, &errors)) + { + ChipLogError(Zcl, "Failed to parse JSON: %s\n", errors.c_str()); + return; + } + + // Validate and access JSON data safely + if (!value.isObject()) + { + ChipLogError(Zcl, "Invalid JSON structure: not an object"); + return; + } + if (!reader.parse(response, value)) { return;