Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions source/binary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -605,8 +605,19 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
case SPV_OPERAND_TYPE_LITERAL_STRING:
case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING: {
const size_t max_words = _.num_words - _.word_index;
std::string string =
spvtools::utils::MakeString(_.words + _.word_index, max_words, false);
std::string string;
if (_.requires_endian_conversion) {
// On big-endian hosts, _.words still holds raw little-endian data at
// this point. Byte-swap before extracting the string characters.
std::vector<uint32_t> swapped(_.words + _.word_index,
_.words + _.word_index + max_words);
const spv_endianness_t endianness = _.endian;
for (auto& w : swapped) w = spvFixWord(w, endianness);
string = spvtools::utils::MakeString(swapped.data(), max_words, false);
} else {
string = spvtools::utils::MakeString(_.words + _.word_index, max_words,
false);
}

if (string.length() == max_words * 4)
return exhaustedInputDiagnostic(inst_offset, opcode, type);
Expand Down
64 changes: 19 additions & 45 deletions tools/objdump/extract_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,45 +21,26 @@

#include "source/latest_version_spirv_header.h"
#include "source/opt/log.h"
#include "source/util/string_utils.h"
#include "spirv-tools/libspirv.hpp"
#include "tools/util/cli_consumer.h"

namespace {

constexpr auto kDefaultEnvironment = SPV_ENV_UNIVERSAL_1_6;

// Extract a string literal from a given range.
// Copies all the characters from `begin` to the first '\0' it encounters, while
// Extract a string literal from a given range of SPIR-V words.
// Copies all the characters up to the first '\0' it encounters, while
// removing escape patterns.
// Not finding a '\0' before reaching `end` fails the extraction.
//
// Returns `true` if the extraction succeeded.
// `output` value is undefined if false is returned.
spv_result_t ExtractStringLiteral(const spv_position_t& loc, const char* begin,
const char* end, std::string* output) {
size_t sourceLength = std::distance(begin, end);
std::string escapedString;
escapedString.resize(sourceLength);

size_t writeIndex = 0;
size_t readIndex = 0;
for (; readIndex < sourceLength; writeIndex++, readIndex++) {
const char read = begin[readIndex];
if (read == '\0') {
escapedString.resize(writeIndex);
output->append(escapedString);
return SPV_SUCCESS;
}

if (read == '\\') {
++readIndex;
}
escapedString[writeIndex] = begin[readIndex];
std::string ExtractAndUnescape(const uint32_t* words, size_t num_words) {
std::string raw = spvtools::utils::MakeString(words, num_words, false);
std::string result;
result.reserve(raw.size());
for (size_t i = 0; i < raw.size(); i++) {
if (raw[i] == '\\' && i + 1 < raw.size()) i++;
result += raw[i];
}

spvtools::Error(spvtools::utils::CLIMessageConsumer, "", loc,
"Missing NULL terminator for literal string.");
return SPV_ERROR_INVALID_BINARY;
return result;
}

spv_result_t extractOpString(const spv_position_t& loc,
Expand All @@ -74,11 +55,9 @@ spv_result_t extractOpString(const spv_position_t& loc,
}

const auto& operand = instruction.operands[1];
const char* stringBegin =
reinterpret_cast<const char*>(instruction.words + operand.offset);
const char* stringEnd = reinterpret_cast<const char*>(
instruction.words + operand.offset + operand.num_words);
return ExtractStringLiteral(loc, stringBegin, stringEnd, output);
*output =
ExtractAndUnescape(instruction.words + operand.offset, operand.num_words);
return SPV_SUCCESS;
}

spv_result_t extractOpSourceContinued(
Expand All @@ -94,11 +73,9 @@ spv_result_t extractOpSourceContinued(
}

const auto& operand = instruction.operands[0];
const char* stringBegin =
reinterpret_cast<const char*>(instruction.words + operand.offset);
const char* stringEnd = reinterpret_cast<const char*>(
instruction.words + operand.offset + operand.num_words);
return ExtractStringLiteral(loc, stringBegin, stringEnd, output);
output->append(ExtractAndUnescape(instruction.words + operand.offset,
operand.num_words));
return SPV_SUCCESS;
}

spv_result_t extractOpSource(const spv_position_t& loc,
Expand All @@ -124,11 +101,8 @@ spv_result_t extractOpSource(const spv_position_t& loc,
return SPV_SUCCESS;
}

const char* stringBegin =
reinterpret_cast<const char*>(instruction.words + 4);
const char* stringEnd =
reinterpret_cast<const char*>(instruction.words + instruction.num_words);
return ExtractStringLiteral(loc, stringBegin, stringEnd, code);
*code = ExtractAndUnescape(instruction.words + 4, instruction.num_words - 4);
return SPV_SUCCESS;
}

} // namespace
Expand Down