diff --git a/trunk/conf/edge.token.traverse.conf b/trunk/conf/edge.token.traverse.conf
index 9d6ba4ce8e..9b75a3dccb 100644
--- a/trunk/conf/edge.token.traverse.conf
+++ b/trunk/conf/edge.token.traverse.conf
@@ -2,7 +2,7 @@
# @see https://ossrs.net/lts/zh-cn/docs/v4/doc/drm
# @see full.conf for detail config.
-listen 1935
+listen 1935;
max_connections 1000;
daemon off;
srs_log_tank console;
diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf
index 7e68466480..db3965000a 100644
--- a/trunk/conf/full.conf
+++ b/trunk/conf/full.conf
@@ -2687,7 +2687,7 @@ vhost stream.transcode.srs.com {
#
# @see https://github.com/ossrs/srs/issues/1399
#############################################################################################
-include include.vhost.conf;
+include ./conf/include.vhost.conf;
#############################################################################################
# The origin cluster section
diff --git a/trunk/conf/http.heartbeat.conf b/trunk/conf/http.heartbeat.conf
index d15ff6a56d..d2125ed332 100644
--- a/trunk/conf/http.heartbeat.conf
+++ b/trunk/conf/http.heartbeat.conf
@@ -1,7 +1,7 @@
# the config for srs http heartbeat, report its info to api-server
# @see full.conf for detail config.
-listen 1935
+listen 1935;
max_connections 1000;
daemon off;
srs_log_tank console;
diff --git a/trunk/doc/CHANGELOG.md b/trunk/doc/CHANGELOG.md
index 7d49a8cf3a..a6d206da55 100644
--- a/trunk/doc/CHANGELOG.md
+++ b/trunk/doc/CHANGELOG.md
@@ -7,6 +7,7 @@ The changelog for SRS.
## SRS 6.0 Changelog
+* v6.0, 2024-07-08, Merge [#4042](https://github.com/ossrs/srs/pull/4042): Refine config directive token parsing. v6.0.135 (#4042)
* v6.0, 2024-07-04, Merge [#4106](https://github.com/ossrs/srs/pull/4106): SmartPtr: Fix SRT source memory leaking. v6.0.134 (#4106)
* v6.0, 2024-06-29, Merge [#4077](https://github.com/ossrs/srs/pull/4077): Fix misspelling error in app config. v6.0.133 (#4077)
* v6.0, 2024-06-29, Merge [#4102](https://github.com/ossrs/srs/pull/4102): SmartPtr: Support detect memory leak by valgrind. v6.0.132 (#4102)
diff --git a/trunk/scripts/verify_confs.sh b/trunk/scripts/verify_confs.sh
new file mode 100755
index 0000000000..7e7233bfe2
--- /dev/null
+++ b/trunk/scripts/verify_confs.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+TRUNK_DIR=$(dirname $(realpath -q $0))/..
+
+pushd $TRUNK_DIR > /dev/null
+
+SRS_EXE=$(pwd)/objs/srs
+
+if [ ! -f ${SRS_EXE} ]; then
+ echo "${SRS_EXE} not exist"
+ exit -1
+fi
+
+if [ ! -x ${SRS_EXE} ]; then
+ echo "${SRS_EXE} not executable"
+ exit -2
+fi
+
+for f in conf/*.conf
+do
+ if [ -f $f ]; then
+ # skip below conf
+ if [[ $f == "conf/full.conf" ||
+ $f == "conf/hls.edge.conf" ||
+ $f == "conf/nginx.proxy.conf" ||
+ $f == "conf/include.vhost.conf" ]]; then
+ continue
+ fi
+
+ ${SRS_EXE} -t -c $f
+ RET=$?
+ if [ $RET -ne 0 ]; then
+ echo "please check $f"
+ popd > /dev/null
+ exit $RET
+ fi
+ fi
+done
+
+popd > /dev/null
diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp
index 07146a6790..eb7a356a26 100644
--- a/trunk/src/app/srs_app_config.cpp
+++ b/trunk/src/app/srs_app_config.cpp
@@ -1202,9 +1202,15 @@ srs_error_t SrsConfDirective::read_token(SrsConfigBuffer* buffer, vector
char ch = *buffer->pos++;
- if (ch == SRS_LF) {
- buffer->line++;
+ if (ch == SRS_LF || ch == SRS_CR) {
+ if (ch == SRS_LF) {
+ buffer->line++;
+ }
+
sharp_comment = false;
+ if (args.size() > 0) {
+ return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "line %d: unexpected end of line to parse token %s", buffer->line - 1, args[0].c_str());
+ }
}
if (sharp_comment) {
@@ -1305,7 +1311,7 @@ srs_error_t SrsConfDirective::read_token(SrsConfigBuffer* buffer, vector
args.push_back(word_str);
}
srs_freepa(aword);
-
+
if (ch == ';') {
state = SrsDirectiveStateEntire;
return err;
@@ -1314,6 +1320,10 @@ srs_error_t SrsConfDirective::read_token(SrsConfigBuffer* buffer, vector
state = SrsDirectiveStateBlockStart;
return err;
}
+
+ if ((ch == SRS_LF || ch == SRS_CR) && args.size() > 0) {
+ return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "line %d: unexpected end of line to parse token %s", buffer->line - 1, args[0].c_str());
+ }
}
}
}
@@ -2378,7 +2388,7 @@ srs_error_t SrsConfig::check_normal_config()
string n = conf->at(i)->name;
if (n != "enabled" && n != "listen" && n != "maxbw"
&& n != "mss" && n != "latency" && n != "recvlatency"
- && n != "peerlatency" && n != "connect_timeout"
+ && n != "peerlatency" && n != "connect_timeout" && n != "peer_idle_timeout"
&& n != "sendbuf" && n != "recvbuf" && n != "payloadsize"
&& n != "default_app" && n != "sei_filter" && n != "mix_correct"
&& n != "tlpktdrop" && n != "tsbpdmode" && n != "passphrase" && n != "pbkeylen") {
diff --git a/trunk/src/core/srs_core_version6.hpp b/trunk/src/core/srs_core_version6.hpp
index db87015415..a961f89592 100644
--- a/trunk/src/core/srs_core_version6.hpp
+++ b/trunk/src/core/srs_core_version6.hpp
@@ -9,6 +9,6 @@
#define VERSION_MAJOR 6
#define VERSION_MINOR 0
-#define VERSION_REVISION 134
+#define VERSION_REVISION 135
#endif
diff --git a/trunk/src/utest/srs_utest.cpp b/trunk/src/utest/srs_utest.cpp
index d8ca03562c..9a9dca5dcb 100644
--- a/trunk/src/utest/srs_utest.cpp
+++ b/trunk/src/utest/srs_utest.cpp
@@ -223,7 +223,7 @@ VOID TEST(SampleTest, ContextTest)
cache[0] = cid;
}
-MockProtectedBuffer::MockProtectedBuffer() : size_(0), data_(NULL), raw_memory_(NULL)
+MockProtectedBuffer::MockProtectedBuffer() : raw_memory_(NULL), size_(0), data_(NULL)
{
}
diff --git a/trunk/src/utest/srs_utest_config.cpp b/trunk/src/utest/srs_utest_config.cpp
index 6bed81306c..a2472e4197 100644
--- a/trunk/src/utest/srs_utest_config.cpp
+++ b/trunk/src/utest/srs_utest_config.cpp
@@ -400,6 +400,24 @@ VOID TEST(ConfigDirectiveTest, ParseArgsSpace)
EXPECT_EQ(0, (int) conf.directives.size());
}
}
+
+ if (true) {
+ vector usecases;
+ usecases.push_back("include\rtest;");
+ usecases.push_back("include\ntest;");
+ usecases.push_back("include \r \n \r\n \n\rtest;");
+
+ for (int i = 0; i < (int)usecases.size(); i++) {
+ string usecase = usecases.at(i);
+
+ MockSrsConfigBuffer buf(usecase);
+ SrsConfDirective conf;
+ HELPER_ASSERT_FAILED(conf.parse(&buf));
+ EXPECT_EQ(0, (int) conf.name.length());
+ EXPECT_EQ(0, (int) conf.args.size());
+ EXPECT_EQ(0, (int) conf.directives.size());
+ }
+ }
if (true) {
vector usecases;
@@ -407,9 +425,6 @@ VOID TEST(ConfigDirectiveTest, ParseArgsSpace)
usecases.push_back("include test;");
usecases.push_back("include test;");
usecases.push_back("include test;");;
- usecases.push_back("include\rtest;");
- usecases.push_back("include\ntest;");
- usecases.push_back("include \r \n \r\n \n\rtest;");
MockSrsConfig config;
config.mock_include("test", "listen 1935;");
@@ -433,6 +448,102 @@ VOID TEST(ConfigDirectiveTest, ParseArgsSpace)
}
}
+VOID TEST(ConfigDirectiveTest, ParseInvalidEndOfLine)
+{
+ srs_error_t err;
+
+ if (true) {
+ MockSrsConfigBuffer buf("dir0 \narg0;dir1 arg1;");
+ SrsConfDirective conf;
+ HELPER_ASSERT_FAILED(conf.parse(&buf));
+ EXPECT_EQ(0, (int) conf.name.length());
+ EXPECT_EQ(0, (int) conf.args.size());
+ EXPECT_EQ(0, (int) conf.directives.size());
+ }
+
+ if (true) {
+ MockSrsConfigBuffer buf("dir0\n arg0;dir1 arg1;");
+ SrsConfDirective conf;
+ HELPER_ASSERT_FAILED(conf.parse(&buf));
+ EXPECT_EQ(0, (int) conf.name.length());
+ EXPECT_EQ(0, (int) conf.args.size());
+ EXPECT_EQ(0, (int) conf.directives.size());
+ }
+
+ if (true) {
+ MockSrsConfigBuffer buf("dir0 arg0\n;dir1 arg1;");
+ SrsConfDirective conf;
+ HELPER_ASSERT_FAILED(conf.parse(&buf));
+ EXPECT_EQ(0, (int) conf.name.length());
+ EXPECT_EQ(0, (int) conf.args.size());
+ EXPECT_EQ(0, (int) conf.directives.size());
+ }
+
+ if (true) {
+ MockSrsConfigBuffer buf("dir0 \rarg0;dir1 arg1;");
+ SrsConfDirective conf;
+ HELPER_ASSERT_FAILED(conf.parse(&buf));
+ EXPECT_EQ(0, (int) conf.name.length());
+ EXPECT_EQ(0, (int) conf.args.size());
+ EXPECT_EQ(0, (int) conf.directives.size());
+ }
+
+ if (true) {
+ MockSrsConfigBuffer buf("dir0 arg0\r;dir1 arg1;");
+ SrsConfDirective conf;
+ HELPER_ASSERT_FAILED(conf.parse(&buf));
+ EXPECT_EQ(0, (int) conf.name.length());
+ EXPECT_EQ(0, (int) conf.args.size());
+ EXPECT_EQ(0, (int) conf.directives.size());
+ }
+
+ if (true) {
+ MockSrsConfigBuffer buf("dir0 \n { dir1 arg1; }");
+ SrsConfDirective conf;
+ HELPER_ASSERT_FAILED(conf.parse(&buf));
+ EXPECT_EQ(0, (int) conf.name.length());
+ EXPECT_EQ(0, (int) conf.args.size());
+ EXPECT_EQ(0, (int) conf.directives.size());
+ }
+
+
+ if (true) {
+ MockSrsConfigBuffer buf("dir0 arg0;dir1\n arg1;");
+ SrsConfDirective conf;
+ HELPER_ASSERT_FAILED(conf.parse(&buf));
+ EXPECT_EQ(0, (int) conf.name.length());
+ EXPECT_EQ(0, (int) conf.args.size());
+ EXPECT_EQ(1, (int) conf.directives.size());
+
+ SrsConfDirective& dir0 = *conf.directives.at(0);
+ EXPECT_STREQ("dir0", dir0.name.c_str());
+ EXPECT_EQ(1, (int)dir0.args.size());
+ EXPECT_STREQ("arg0", dir0.arg0().c_str());
+ EXPECT_EQ(0, (int)dir0.directives.size());
+ }
+
+ if (true) {
+ MockSrsConfigBuffer buf("dir0 arg0;dir1 arg1;");
+ SrsConfDirective conf;
+ HELPER_ASSERT_SUCCESS(conf.parse(&buf));
+ EXPECT_EQ(0, (int)conf.name.length());
+ EXPECT_EQ(0, (int)conf.args.size());
+ EXPECT_EQ(2, (int)conf.directives.size());
+
+ SrsConfDirective& dir0 = *conf.directives.at(0);
+ EXPECT_STREQ("dir0", dir0.name.c_str());
+ EXPECT_EQ(1, (int)dir0.args.size());
+ EXPECT_STREQ("arg0", dir0.arg0().c_str());
+ EXPECT_EQ(0, (int)dir0.directives.size());
+
+ SrsConfDirective& dir1 = *conf.directives.at(1);
+ EXPECT_STREQ("dir1", dir1.name.c_str());
+ EXPECT_EQ(1, (int)dir1.args.size());
+ EXPECT_STREQ("arg1", dir1.arg0().c_str());
+ EXPECT_EQ(0, (int)dir1.directives.size());
+ }
+}
+
VOID TEST(ConfigDirectiveTest, Parse2SingleDirs)
{
srs_error_t err;
@@ -829,30 +940,7 @@ VOID TEST(ConfigDirectiveTest, ParseLine4)
MockSrsConfigBuffer buf("dir0 {\n\ndir1 \n\narg0;dir2 arg1;}");
SrsConfDirective conf;
- HELPER_ASSERT_SUCCESS(conf.parse(&buf));
- EXPECT_EQ(0, (int)conf.name.length());
- EXPECT_EQ(0, (int)conf.args.size());
- EXPECT_EQ(1, (int)conf.directives.size());
-
- SrsConfDirective& dir0 = *conf.directives.at(0);
- EXPECT_STREQ("dir0", dir0.name.c_str());
- EXPECT_EQ(0, (int)dir0.args.size());
- EXPECT_EQ(2, (int)dir0.directives.size());
- EXPECT_EQ(1, (int)dir0.conf_line);
-
- SrsConfDirective& dir1 = *dir0.directives.at(0);
- EXPECT_STREQ("dir1", dir1.name.c_str());
- EXPECT_EQ(1, (int)dir1.args.size());
- EXPECT_STREQ("arg0", dir1.arg0().c_str());
- EXPECT_EQ(0, (int)dir1.directives.size());
- EXPECT_EQ(3, (int)dir1.conf_line);
-
- SrsConfDirective& dir2 = *dir0.directives.at(1);
- EXPECT_STREQ("dir2", dir2.name.c_str());
- EXPECT_EQ(1, (int)dir2.args.size());
- EXPECT_STREQ("arg1", dir2.arg0().c_str());
- EXPECT_EQ(0, (int)dir2.directives.size());
- EXPECT_EQ(5, (int)dir2.conf_line);
+ HELPER_ASSERT_FAILED(conf.parse(&buf));
}
VOID TEST(ConfigDirectiveTest, ParseLineNormal)