Author SHA1 Message Date
pancake 1e84eb2ae5 Use r_name_check instead of json_utils::valid_flag_name 2026-09-28 17:12:03 +02:00
9 changed files with 18 additions and 31 deletions

No files matched your search

+1 -9
View File
@@ -4,6 +4,7 @@
// This file is licensed under the Human-Origin Source License v1.0.
// See LICENSE.
#include "json_utils.hpp"
#include <r_util.h>
#include <cctype>
#include <cstdio>
@@ -73,15 +74,6 @@ std::string r2_quote(std::string_view s) {
return out;
}
bool valid_flag_name(std::string_view name) {
if (name.empty()) return false;
for (unsigned char c : name) {
const bool ok = (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
(c >= '0' && c <= '9') || c == '.' || c == '_' || c == '$';
if (!ok) return false;
}
return true;
}
bool valid_type_text(std::string_view type) {
if (type.empty()) return false;
+1 -6
View File
@@ -33,12 +33,7 @@ int64_t i64_addr(const nlohmann::json& obj, int64_t dflt = 0);
// not a shell, but spaces, quotes and backslashes need escaping in CC args.
std::string r2_quote(std::string_view s);
// True iff `name` is safe to splice into an r2 flag command unquoted: a
// non-empty string of [A-Za-z0-9._$] only. This is roughly r2's own flag-name
// charset; rejecting anything else prevents a name with spaces or command
// separators (`;`, `@`, `|`, backtick, …) from breaking parsing or injecting
// extra r2 commands. Use to gate INSERT/UPDATE on the flags/bookmarks tables.
bool valid_flag_name(std::string_view name);
// True iff `type` is a safe C type string to splice into an r2 `afvt` command
// unquoted: a non-empty string of type-syntax characters only —
+2 -2
View File
@@ -126,7 +126,7 @@ void register_bookmarks_table(Session& s) {
[](const BookmarkRow& r) { return r.name; },
[be = s.backend_ptr()](BookmarkRow& r, const char* v) -> bool {
if (!v || !*v) return false;
if (!json_utils::valid_flag_name(v)) {
if (!r_name_check(v.c_str())) {
xsql::set_vtab_error(
"bookmarks: name must be [A-Za-z0-9._$] (no spaces or r2 metacharacters)");
return false;
@@ -180,7 +180,7 @@ void register_bookmarks_table(Session& s) {
xsql::set_vtab_error("bookmarks: INSERT requires a non-empty name");
return false;
}
if (!json_utils::valid_flag_name(name)) {
if (!r_name_check(name.c_str())) {
xsql::set_vtab_error(
"bookmarks: name must be [A-Za-z0-9._$] (no spaces or r2 metacharacters)");
return false;
+3 -3
View File
@@ -127,7 +127,7 @@ void build_flags(Backend* be, std::vector<FlagRow>& rows) {
const std::string name = json_utils::str(sp, "name");
// A space name is spliced into a command, so it gets the same charset gate
// as every other name this project sends to radare2.
if (name.empty() || !json_utils::valid_flag_name(name)) continue;
if (name.empty() || !r_name_check(name.c_str())) continue;
if (json_utils::i64(sp, "count") == 0) continue; // nothing to attribute
// One command, not three: selecting a flagspace is session state, so the
@@ -163,7 +163,7 @@ void register_flags_table(Session& s) {
[](const FlagRow& r) { return r.name; },
[be = s.backend_ptr()](FlagRow& r, const char* v) -> bool {
if (!v || !*v) return false;
if (!json_utils::valid_flag_name(v)) {
if (!r_name_check(v.c_str())) {
xsql::set_vtab_error(
"flags: name must be [A-Za-z0-9._$] (no spaces or r2 metacharacters)");
return false;
@@ -260,7 +260,7 @@ void register_flags_table(Session& s) {
xsql::set_vtab_error("flags: INSERT requires a non-empty name");
return false;
}
if (!json_utils::valid_flag_name(name)) {
if (!r_name_check(name.c_str())) {
xsql::set_vtab_error(
"flags: name must be [A-Za-z0-9._$] (no spaces or r2 metacharacters)");
return false;
+3 -3
View File
@@ -12,7 +12,7 @@
// radare2's own command handler, seeked to the target address, called
// directly without evaluating its command-chaining grammar (`;`/`@`/`|`/
// backtick) at all. This is an ADDITIONAL layer alongside this table's
// existing grammar/value validation (`valid_flag_name`, `valid_c_signature`,
// existing grammar/value validation (`r_name_check`, `valid_c_signature`,
// the `calling_convention_exists` check on `calltype`) — none replaces the
// others. On every other backend (r2pipe, mock) cmd_noeval reports
// unsupported and the exact same `cmd()` + spliced `@ <addr>` string this
@@ -218,7 +218,7 @@ void register_funcs_table(Session& s) {
[](const FuncRow& r) { return r.name; },
[be = s.backend_ptr()](FuncRow& r, const char* v) -> bool {
if (!v || !*v) return false;
if (!json_utils::valid_flag_name(v)) {
if (!r_name_check(v.c_str())) {
xsql::set_vtab_error(
"funcs: name must be [A-Za-z0-9._$] (no spaces or r2 metacharacters)");
return false;
@@ -371,7 +371,7 @@ void register_funcs_table(Session& s) {
// Optional best-effort naming; a failed afn does not undo the af above.
if (argc > 1 && !argv[1].is_null()) {
const char* name = argv[1].as_c_str();
if (name && *name && json_utils::valid_flag_name(name)) {
if (name && *name && r_name_check(name.c_str())) {
(void)dispatch_write(be, addr, std::string("afn ") + name);
}
}
+1 -1
View File
@@ -99,7 +99,7 @@ void register_io_maps_table(Session& s) {
std::string name;
if (argc > 3 && !argv[3].is_null()) {
name = argv[3].as_c_str();
if (!name.empty() && !json_utils::valid_flag_name(name.c_str())) {
if (!name.empty() && !r_name_check(name.c_str())) {
xsql::set_vtab_error("io_maps: name must be [A-Za-z0-9._$] (no spaces)");
return false;
}
+4 -4
View File
@@ -49,7 +49,7 @@
// `dispatch_write(be, addr, command)` helper every sibling write-capable
// table (`comments`, `funcs`, `flags`, `bookmarks`, `types`, `patches`)
// already uses. This is an ADDITIONAL layer alongside this table's existing
// grammar validation (`valid_flag_name`/`valid_type_text`), never a
// grammar validation (`r_name_check`/`valid_type_text`), never a
// replacement for it. On the r2pipe backend, `cmd_noeval` reports unsupported
// and the exact `afvn`/`afvt` command text this table always issued runs
// unchanged.
@@ -191,12 +191,12 @@ void register_locals_table(Session& s) {
[](const LocalRow& r) { return r.name; },
[be = s.backend_ptr()](LocalRow& r, const char* v) -> bool {
if (!v || !*v) return false;
if (!json_utils::valid_flag_name(v)) {
if (!r_name_check(v.c_str())) {
xsql::set_vtab_error(
"locals: name must be [A-Za-z0-9._$] (no spaces or r2 metacharacters)");
return false;
}
if (!json_utils::valid_flag_name(r.name)) {
if (!r_name_check(r.name.c_str())) {
xsql::set_vtab_error(
"locals: existing name contains r2 command metacharacters");
return false;
@@ -245,7 +245,7 @@ void register_locals_table(Session& s) {
"locals: type contains an r2 metacharacter (@ ; | ` \" $ etc.)");
return false;
}
if (!json_utils::valid_flag_name(r.name)) {
if (!r_name_check(r.name.c_str())) {
xsql::set_vtab_error(
"locals: existing name contains r2 command metacharacters");
return false;
+1 -1
View File
@@ -42,7 +42,7 @@ void register_projects_table(Session& s) {
})
.column_text("name", [](const ProjectRow& r) { return r.name; })
.deletable([be = s.backend_ptr()](ProjectRow& r) -> bool {
if (r.name.empty() || !json_utils::valid_flag_name(r.name)) {
if (r.name.empty() || !r_name_check(r.name.c_str())) {
xsql::set_vtab_error("projects: refusing to delete an unsafe/empty project name");
return false;
}
+2 -2
View File
@@ -148,7 +148,7 @@ void register_types_table(Session& s) {
// SQL creates empty struct/union/enum shells and deletes types by name.
// Full declarations use radare2's native td command.
.deletable([be = s.backend_ptr()](TypeRow& r) -> bool {
if (r.name.empty() || !json_utils::valid_flag_name(r.name)) {
if (r.name.empty() || !r_name_check(r.name.c_str())) {
xsql::set_vtab_error("types: refusing to delete an unsafe/empty type name");
return false;
}
@@ -177,7 +177,7 @@ void register_types_table(Session& s) {
const char* kind_c = argv[2].as_c_str();
const std::string name = name_c ? name_c : "";
const std::string kind = kind_c ? kind_c : "";
if (name.empty() || !json_utils::valid_flag_name(name)) {
if (name.empty() || !r_name_check(name.c_str())) {
xsql::set_vtab_error("types: refusing to create an unsafe/empty type name");
return false;
}