Skip to content

Commit

Permalink
[chip-tool] Add support for hex:/str: prefixed OCTET_STRING for compl…
Browse files Browse the repository at this point in the history
…ex arguments instead of always assuming this is an hex string (#23967)
  • Loading branch information
vivien-apple authored and pull[bot] committed Nov 12, 2023
1 parent 1ed7013 commit 2810337
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 17 deletions.
56 changes: 49 additions & 7 deletions examples/chip-tool/commands/clusters/ComplexArgument.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,21 @@
*
*/

/**
* This file allocate/free memory using the chip platform abstractions
* (Platform::MemoryCalloc and Platform::MemoryFree) for hosting a subset of the
* data model internal types until they are consumed by the DataModel::Encode machinery:
* - chip::app:DataModel::List<T>
* - chip::ByteSpan
* - chip::CharSpan
*
* Memory allocation happens during the 'Setup' phase, while memory deallocation happens
* during the 'Finalize' phase.
*
* The 'Finalize' phase during the destructor phase, and if needed, 'Finalize' will call
* the 'Finalize' phase of its descendant.
*/

#pragma once

#include <app-common/zap-generated/cluster-objects.h>
Expand Down Expand Up @@ -173,17 +188,44 @@ class ComplexArgumentParser
return CHIP_ERROR_INVALID_ARGUMENT;
}

if (strlen(value.asCString()) % 2 != 0)
auto str = value.asString();
auto size = str.size();
uint8_t * buffer = nullptr;

if (IsStrString(str.c_str()))
{
ChipLogError(chipTool, "Error while encoding %s as an octet string: Odd number of characters.", label);
return CHIP_ERROR_INVALID_STRING_LENGTH;
// Skip the prefix
str.erase(0, kStrStringPrefixLen);
size = str.size();

buffer = static_cast<uint8_t *>(chip::Platform::MemoryCalloc(size, sizeof(uint8_t)));
memcpy(buffer, str.c_str(), size);
}
else
{
if (IsHexString(str.c_str()))
{
// Skip the prefix
str.erase(0, kHexStringPrefixLen);
size = str.size();
}

if (size % 2 != 0)
{
ChipLogError(chipTool, "Error while encoding %s as a hex string: Odd number of characters.", label);
return CHIP_ERROR_INVALID_STRING_LENGTH;
}

size_t size = strlen(value.asCString());
auto buffer = static_cast<uint8_t *>(chip::Platform::MemoryCalloc(size / 2, sizeof(uint8_t)));
size_t octetCount = chip::Encoding::HexToBytes(value.asCString(), size, buffer, size / 2);
buffer = static_cast<uint8_t *>(chip::Platform::MemoryCalloc(size / 2, sizeof(uint8_t)));
size = chip::Encoding::HexToBytes(str.c_str(), size, buffer, size / 2);
if (size == 0)
{
ChipLogError(chipTool, "Error while encoding %s as a hex string.", label);
return CHIP_ERROR_INTERNAL;
}
}

request = chip::ByteSpan(buffer, octetCount);
request = chip::ByteSpan(buffer, size);
return CHIP_NO_ERROR;
}

Expand Down
2 changes: 2 additions & 0 deletions examples/chip-tool/commands/clusters/JsonParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

#pragma once

#include "../common/CustomStringPrefix.h"

#include <json/json.h>
#include <lib/core/Optional.h>

Expand Down
20 changes: 10 additions & 10 deletions examples/chip-tool/commands/common/Command.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
*/

#include "Command.h"
#include "CustomStringPrefix.h"
#include "platform/PlatformManager.h"

#include <functional>
#include <netdb.h>
Expand Down Expand Up @@ -362,10 +364,9 @@ bool Command::InitArgument(size_t argIndex, char * argValue)
// We support two ways to pass an octet string argument. If it happens
// to be all-ASCII, you can just pass it in. Otherwise you can pass in
// "hex:" followed by the hex-encoded bytes.
size_t argLen = strlen(argValue);
static constexpr char hexPrefix[] = "hex:";
constexpr size_t prefixLen = ArraySize(hexPrefix) - 1; // Don't count the null
if (strncmp(argValue, hexPrefix, prefixLen) == 0)
size_t argLen = strlen(argValue);

if (IsHexString(argValue))
{
// Hex-encoded. Decode it into a temporary buffer first, so if we
// run into errors we can do correct "argument is not valid" logging
Expand All @@ -381,7 +382,8 @@ bool Command::InitArgument(size_t argIndex, char * argValue)
return false;
}

size_t octetCount = chip::Encoding::HexToBytes(argValue + prefixLen, argLen - prefixLen, buffer.Get(), argLen);
size_t octetCount =
chip::Encoding::HexToBytes(argValue + kHexStringPrefixLen, argLen - kHexStringPrefixLen, buffer.Get(), argLen);
if (octetCount == 0)
{
return false;
Expand All @@ -393,13 +395,11 @@ bool Command::InitArgument(size_t argIndex, char * argValue)
}

// Just ASCII. Check for the "str:" prefix.
static constexpr char strPrefix[] = "str:";
constexpr size_t strPrefixLen = ArraySize(strPrefix) - 1; // Don't count the null
if (strncmp(argValue, strPrefix, strPrefixLen) == 0)
if (IsStrString(argValue))
{
// Skip the prefix
argValue += strPrefixLen;
argLen -= strPrefixLen;
argValue += kStrStringPrefixLen;
argLen -= kStrStringPrefixLen;
}
*value = chip::ByteSpan(chip::Uint8::from_char(argValue), argLen);
return true;
Expand Down
35 changes: 35 additions & 0 deletions examples/chip-tool/commands/common/CustomStringPrefix.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2022 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

#pragma once

static constexpr char kHexStringPrefix[] = "hex:";
constexpr size_t kHexStringPrefixLen = ArraySize(kHexStringPrefix) - 1; // Don't count the null

static constexpr char kStrStringPrefix[] = "str:";
constexpr size_t kStrStringPrefixLen = ArraySize(kStrStringPrefix) - 1; // Don't count the null

inline bool IsHexString(const char * str)
{
return strncmp(str, kHexStringPrefix, kHexStringPrefixLen) == 0;
}

inline bool IsStrString(const char * str)
{
return strncmp(str, kStrStringPrefix, kStrStringPrefixLen) == 0;
}

0 comments on commit 2810337

Please sign in to comment.