mirror of
https://github.com/radareorg/r2xsql.git
synced 2026-11-07 22:42:50 -10:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1e84eb2ae5 |
No files matched your search
@@ -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;
|
||||
|
||||
@@ -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 —
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user