Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ntcore] Check id ranges in control messages #7726

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
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
5 changes: 5 additions & 0 deletions ntcore/doc/networktables4.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,11 @@ Clients may publish a value at any time following clock synchronization. Client

Clients should subscribe to the `$sub$<topic>` meta topic for each topic published and use this metadata to determine how frequently to send updates to the network. However, this is not required--clients may choose to ignore this and send updates at any time.

[[ids]]
=== IDs and UIDs

IDs and UIDs should be selected by clients and servers to be as small as possible for transmission efficiency. Clients and servers should support a signed 32-bit range for IDs and UIDs, but exceptions can be made for implementation reasons. Clients and servers must ignore messages with unsupported IDs and UIDs, and should report a diagnostic if this occurs.

[[meta-topics]]
=== Server-Published Meta Topics

Expand Down
43 changes: 43 additions & 0 deletions ntcore/src/main/native/cpp/net/WireDecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,12 @@ static bool WireDecodeTextImpl(std::string_view in, T& out,
goto err;
}

// limit to 32-bit range and exclude endpoints used by DenseMap
if (pubuid >= 0x7fffffffLL || pubuid <= (-0x7fffffffLL - 1)) {
error = "pubuid out of range";
goto err;
}

// properties; allow missing (treated as empty)
wpi::json* properties = nullptr;
auto propertiesIt = params->find("properties");
Expand All @@ -200,6 +206,12 @@ static bool WireDecodeTextImpl(std::string_view in, T& out,
goto err;
}

// limit to 32-bit range and exclude endpoints used by DenseMap
if (pubuid >= 0x7fffffffLL || pubuid <= (-0x7fffffffLL - 1)) {
error = "pubuid out of range";
goto err;
}

// complete
out.ClientUnpublish(pubuid);
rv = true;
Expand Down Expand Up @@ -231,6 +243,12 @@ static bool WireDecodeTextImpl(std::string_view in, T& out,
goto err;
}

// limit to 32-bit range and exclude endpoints used by DenseMap
if (subuid >= 0x7fffffffLL || subuid <= (-0x7fffffffLL - 1)) {
error = "subuid out of range";
goto err;
}

// options
PubSubOptionsImpl options;
auto optionsIt = params->find("options");
Expand Down Expand Up @@ -303,6 +321,12 @@ static bool WireDecodeTextImpl(std::string_view in, T& out,
goto err;
}

// limit to 32-bit range and exclude endpoints used by DenseMap
if (subuid >= 0x7fffffffLL || subuid <= (-0x7fffffffLL - 1)) {
error = "pubuid out of range";
goto err;
}

// complete
out.ClientUnsubscribe(subuid);
rv = true;
Expand All @@ -324,6 +348,12 @@ static bool WireDecodeTextImpl(std::string_view in, T& out,
goto err;
}

// limit to 32-bit range and exclude endpoints used by DenseMap
if (id >= 0x7fffffffLL || id <= (-0x7fffffffLL - 1)) {
error = "id out of range";
goto err;
}

// type
auto typeStr = ObjGetString(*params, "type", &error);
if (!typeStr) {
Expand All @@ -339,6 +369,13 @@ static bool WireDecodeTextImpl(std::string_view in, T& out,
error = "pubuid value must be a number";
goto err;
}

// limit to 32-bit range and exclude endpoints used by DenseMap
if (val >= 0x7fffffffLL || val <= (-0x7fffffffLL - 1)) {
error = "pubuid out of range";
goto err;
}

pubuid = val;
}

Expand Down Expand Up @@ -369,6 +406,12 @@ static bool WireDecodeTextImpl(std::string_view in, T& out,
goto err;
}

// limit to 32-bit range and exclude endpoints used by DenseMap
if (id >= 0x7fffffffLL || id <= (-0x7fffffffLL - 1)) {
error = "id out of range";
goto err;
}

// complete
out.ServerUnannounce(*name, id);
} else if (*method == PropertiesUpdateMsg::kMethodStr) {
Expand Down
16 changes: 16 additions & 0 deletions ntcore/src/test/native/cpp/server/ServerImplTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -423,4 +423,20 @@ TEST_F(ServerImplTest, ZeroTimestampNegativeTime) {
}
}

TEST_F(ServerImplTest, InvalidPubUid) {
EXPECT_CALL(logger, Call(_, _, _, "0: pubuid out of range"));
server.SetLocal(&local, &queue);

// connect client
::testing::StrictMock<net::MockWireConnection> wire;
MockSetPeriodicFunc setPeriodic;
auto [name, id] = server.AddClient("test", "connInfo", false, wire,
setPeriodic.AsStdFunction());

server.ProcessIncomingText(
id,
"[{\"method\":\"publish\",\"params\":{\"type\":\"string\",\"name\":"
"\"myvalue\",\"pubuid\":2147483647,\"properties\":{}}}]");
}

} // namespace nt
Loading