Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
Actor Framework
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
cpp-libs
Actor Framework
Commits
a1ba72cc
Unverified
Commit
a1ba72cc
authored
Jul 11, 2023
by
Dominik Charousset
Committed by
GitHub
Jul 11, 2023
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1477
Validate UTF-8 on WebSocket text payloads
parents
d0cdb60c
423bb432
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
43 additions
and
23 deletions
+43
-23
libcaf_core/caf/sec.hpp
libcaf_core/caf/sec.hpp
+2
-2
libcaf_core/src/detail/rfc3629.cpp
libcaf_core/src/detail/rfc3629.cpp
+7
-4
libcaf_core/src/sec_strings.cpp
libcaf_core/src/sec_strings.cpp
+5
-5
libcaf_core/test/detail/rfc3629.cpp
libcaf_core/test/detail/rfc3629.cpp
+12
-2
libcaf_io/caf/io/basp/connection_state.hpp
libcaf_io/caf/io/basp/connection_state.hpp
+4
-4
libcaf_io/src/io/basp/instance.cpp
libcaf_io/src/io/basp/instance.cpp
+6
-6
libcaf_net/src/net/web_socket/framing.cpp
libcaf_net/src/net/web_socket/framing.cpp
+5
-0
libcaf_net/src/net/web_socket/lower_layer.cpp
libcaf_net/src/net/web_socket/lower_layer.cpp
+2
-0
No files found.
libcaf_core/caf/sec.hpp
View file @
a1ba72cc
...
...
@@ -105,8 +105,8 @@ enum class sec : uint8_t {
incompatible_versions
,
/// Connection refused because of incompatible application IDs.
incompatible_application_ids
,
///
The middleman received a malformed BASP
message from another node.
malformed_
basp_
message
,
///
Received a malformed
message from another node.
malformed_message
,
/// The middleman closed a connection because it failed to serialize or
/// deserialize a payload.
serializing_basp_payload_failed
=
50
,
...
...
libcaf_core/src/detail/rfc3629.cpp
View file @
a1ba72cc
...
...
@@ -42,9 +42,6 @@ constexpr bool is_continuation_byte(std::byte value) noexcept {
bool
validate_rfc3629
(
const
std
::
byte
*
first
,
const
std
::
byte
*
last
)
{
while
(
first
!=
last
)
{
auto
x
=
*
first
++
;
// Null byte (terminator) is not allowed.
if
(
x
==
0
_b
)
return
false
;
// First bit is zero: ASCII character.
if
(
head
<
1
>
(
x
)
==
0b0000
'
0000
_b
)
continue
;
...
...
@@ -72,13 +69,19 @@ bool validate_rfc3629(const std::byte* first, const std::byte* last) {
return
false
;
continue
;
}
// 1111'0
b
xx: 4-byte sequence.
// 1111'0
x
xx: 4-byte sequence.
if
(
head
<
5
>
(
x
)
==
0b1111
'
0000
_b
)
{
// Check if code point is in the valid UTF range.
if
(
x
>
std
::
byte
{
0xf4
})
return
false
;
if
(
first
==
last
||
!
is_continuation_byte
(
*
first
))
return
false
;
// No non-shortest form.
if
(
x
==
0b1111
'
0000
_b
&&
head
<
4
>
(
*
first
)
==
0b1000
'
0000
_b
)
return
false
;
// Check if code point is in the valid UTF range.
if
(
x
==
std
::
byte
{
0xf4
}
&&
*
first
>=
std
::
byte
{
0x90
})
return
false
;
++
first
;
if
(
first
==
last
||
!
is_continuation_byte
(
*
first
++
))
return
false
;
...
...
libcaf_core/src/sec_strings.cpp
View file @
a1ba72cc
...
...
@@ -113,8 +113,8 @@ std::string to_string(sec x) {
return
"caf::sec::incompatible_versions"
;
case
sec
:
:
incompatible_application_ids
:
return
"caf::sec::incompatible_application_ids"
;
case
sec
:
:
malformed_
basp_
message
:
return
"caf::sec::malformed_
basp_
message"
;
case
sec
:
:
malformed_message
:
return
"caf::sec::malformed_message"
;
case
sec
:
:
serializing_basp_payload_failed
:
return
"caf::sec::serializing_basp_payload_failed"
;
case
sec
:
:
redundant_connection
:
...
...
@@ -306,8 +306,8 @@ bool from_string(std::string_view in, sec& out) {
}
else
if
(
in
==
"caf::sec::incompatible_application_ids"
)
{
out
=
sec
::
incompatible_application_ids
;
return
true
;
}
else
if
(
in
==
"caf::sec::malformed_
basp_
message"
)
{
out
=
sec
::
malformed_
basp_
message
;
}
else
if
(
in
==
"caf::sec::malformed_message"
)
{
out
=
sec
::
malformed_message
;
return
true
;
}
else
if
(
in
==
"caf::sec::serializing_basp_payload_failed"
)
{
out
=
sec
::
serializing_basp_payload_failed
;
...
...
@@ -429,7 +429,7 @@ bool from_integer(std::underlying_type_t<sec> in,
case
sec
:
:
unavailable_or_would_block
:
case
sec
:
:
incompatible_versions
:
case
sec
:
:
incompatible_application_ids
:
case
sec
:
:
malformed_
basp_
message
:
case
sec
:
:
malformed_message
:
case
sec
:
:
serializing_basp_payload_failed
:
case
sec
:
:
redundant_connection
:
case
sec
:
:
remote_lookup_failed
:
...
...
libcaf_core/test/detail/rfc3629.cpp
View file @
a1ba72cc
...
...
@@ -96,11 +96,19 @@ constexpr std::byte valid_three_byte_1[] = {0xe0_b, 0xa0_b, 0x80_b};
// Largest valid 3-byte sequence.
constexpr
std
::
byte
valid_three_byte_2
[]
=
{
0xef
_b
,
0xbf
_b
,
0xbf
_b
};
// UTF-8 standard covers code points in the sequences [0x0 - 0x110000)
// Theoretically, a larger value can be encoded in the 4-byte sequence.
// Smallest valid 4-byte sequence.
constexpr
std
::
byte
valid_four_byte_1
[]
=
{
0xf0
_b
,
0x90
_b
,
0x80
_b
,
0x80
_b
};
// Largest valid 4-byte sequence.
constexpr
std
::
byte
valid_four_byte_2
[]
=
{
0xf7
_b
,
0xbf
_b
,
0xbf
_b
,
0xbf
_b
};
// Largest valid 4-byte sequence - code point 0x10FFFF.
constexpr
std
::
byte
valid_four_byte_2
[]
=
{
0xf4
_b
,
0x8f
_b
,
0xbf
_b
,
0xbf
_b
};
// Smallest invalid 4-byte sequence - code point 0x110000.
constexpr
std
::
byte
invalid_four_byte_9
[]
=
{
0xf4
_b
,
0x90
_b
,
0x80
_b
,
0x80
_b
};
// Largest invalid 4-byte sequence - invalid code point.
constexpr
std
::
byte
invalid_four_byte_10
[]
=
{
0xf7
_b
,
0xbf
_b
,
0xbf
_b
,
0xbf
_b
};
// Single line ASCII text.
constexpr
std
::
string_view
ascii_1
=
"Hello World!"
;
...
...
@@ -151,4 +159,6 @@ TEST_CASE("invalid UTF-8 input") {
CHECK
(
!
valid_utf8
(
invalid_four_byte_6
));
CHECK
(
!
valid_utf8
(
invalid_four_byte_7
));
CHECK
(
!
valid_utf8
(
invalid_four_byte_8
));
CHECK
(
!
valid_utf8
(
invalid_four_byte_9
));
CHECK
(
!
valid_utf8
(
invalid_four_byte_10
));
}
libcaf_io/caf/io/basp/connection_state.hpp
View file @
a1ba72cc
...
...
@@ -27,8 +27,8 @@ enum connection_state {
incompatible_versions
,
/// See `sec::incompatible_application_ids`.
incompatible_application_ids
,
/// See `sec::malformed_
basp_
message`.
malformed_
basp_
message
,
/// See `sec::malformed_message`.
malformed_message
,
/// See `sec::serializing_basp_payload_failed`.
serializing_basp_payload_failed
,
/// See `sec::redundant_connection`.
...
...
@@ -55,8 +55,8 @@ inline sec to_sec(connection_state x) noexcept {
return
sec
::
incompatible_versions
;
case
incompatible_application_ids
:
return
sec
::
incompatible_application_ids
;
case
malformed_
basp_
message
:
return
sec
::
malformed_
basp_
message
;
case
malformed_message
:
return
sec
::
malformed_message
;
case
serializing_basp_payload_failed
:
return
sec
::
serializing_basp_payload_failed
;
case
redundant_connection
:
...
...
libcaf_io/src/io/basp/instance.cpp
View file @
a1ba72cc
...
...
@@ -55,17 +55,17 @@ connection_state instance::handle(execution_unit* ctx, new_data_msg& dm,
if
(
payload
->
size
()
!=
hdr
.
payload_len
)
{
CAF_LOG_WARNING
(
"received invalid payload, expected"
<<
hdr
.
payload_len
<<
"bytes, got"
<<
payload
->
size
());
return
err
(
malformed_
basp_
message
);
return
err
(
malformed_message
);
}
}
else
{
binary_deserializer
source
{
ctx
,
dm
.
buf
};
if
(
!
source
.
apply
(
hdr
))
{
CAF_LOG_WARNING
(
"failed to receive header:"
<<
source
.
get_error
());
return
err
(
malformed_
basp_
message
);
return
err
(
malformed_message
);
}
if
(
!
valid
(
hdr
))
{
CAF_LOG_WARNING
(
"received invalid header:"
<<
CAF_ARG
(
hdr
));
return
err
(
malformed_
basp_
message
);
return
err
(
malformed_message
);
}
if
(
hdr
.
payload_len
>
0
)
{
CAF_LOG_DEBUG
(
"await payload before processing further"
);
...
...
@@ -309,11 +309,11 @@ connection_state instance::handle(execution_unit* ctx, connection_handle hdl,
if
(
payload
==
nullptr
)
{
if
(
hdr
.
payload_len
!=
0
)
{
CAF_LOG_WARNING
(
"missing payload"
);
return
malformed_
basp_
message
;
return
malformed_message
;
}
}
else
if
(
hdr
.
payload_len
!=
payload
->
size
())
{
CAF_LOG_WARNING
(
"actual payload size differs from advertised size"
);
return
malformed_
basp_
message
;
return
malformed_message
;
}
// Dispatch by message type.
switch
(
hdr
.
operation
)
{
...
...
@@ -506,7 +506,7 @@ connection_state instance::handle(execution_unit* ctx, connection_handle hdl,
}
default:
{
CAF_LOG_ERROR
(
"invalid operation"
);
return
malformed_
basp_
message
;
return
malformed_message
;
}
}
return
await_header
;
...
...
libcaf_net/src/net/web_socket/framing.cpp
View file @
a1ba72cc
...
...
@@ -4,6 +4,7 @@
#include "caf/net/web_socket/framing.hpp"
#include "caf/detail/rfc3629.hpp"
#include "caf/logger.hpp"
#include "caf/net/http/v1.hpp"
...
...
@@ -202,6 +203,10 @@ ptrdiff_t framing::handle(uint8_t opcode, byte_span payload,
case
detail
:
:
rfc6455
::
text_frame
:
{
std
::
string_view
text
{
reinterpret_cast
<
const
char
*>
(
payload
.
data
()),
payload
.
size
()};
if
(
!
detail
::
rfc3629
::
valid
(
text
))
{
abort_and_shutdown
(
sec
::
malformed_message
,
"invalid UTF-8 sequence"
);
return
-
1
;
}
if
(
up_
->
consume_text
(
text
)
<
0
)
return
-
1
;
break
;
...
...
libcaf_net/src/net/web_socket/lower_layer.cpp
View file @
a1ba72cc
...
...
@@ -24,6 +24,8 @@ void lower_layer::shutdown(const error& reason) {
shutdown
(
status
::
normal_close
,
to_string
(
reason
));
}
else
if
(
reason
.
code
()
==
static_cast
<
uint8_t
>
(
sec
::
protocol_error
))
{
shutdown
(
status
::
protocol_error
,
to_string
(
reason
));
}
else
if
(
reason
.
code
()
==
static_cast
<
uint8_t
>
(
sec
::
malformed_message
))
{
shutdown
(
status
::
inconsistent_data
,
to_string
(
reason
));
}
else
{
shutdown
(
status
::
unexpected_condition
,
to_string
(
reason
));
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment