Skip to content

Commit a4ebf8f

Browse files
authored
Require the configuration file specify an appender to be valid (#533)
* Simplify DOMConfigurator * Require that a properties file has an appender to be valid * In the next ABI, require that a properties file adds an appender to be valid * Log a warning when the configuration file did not add an appender * Upgrade sonarcube version to avoid Github action command injection vulnerability * Improve the layout of a logged XML syntax error
1 parent 93ed279 commit a4ebf8f

30 files changed

+449
-163
lines changed

.github/workflows/sonarcloud.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ jobs:
5555
sudo apt-get install -y libapr1-dev libaprutil1-dev
5656
5757
- name: Install Build Wrapper
58-
uses: SonarSource/sonarqube-scan-action/install-build-wrapper@v4.2.1
58+
uses: SonarSource/sonarqube-scan-action/install-build-wrapper@v5.3.1
5959
env:
6060
SONAR_HOST_URL: ${{ env.SONAR_SERVER_URL }}
6161

@@ -84,7 +84,7 @@ jobs:
8484
-o "$BaseDir/build/coverage.xml"
8585
8686
- name: SonarQube Scan
87-
uses: SonarSource/sonarqube-scan-action@v4.2.1
87+
uses: SonarSource/sonarqube-scan-action@v5.3.1
8888
env:
8989
SONAR_TOKEN: ${{ secrets.SONARCLOUD_TOKEN }}
9090
SONAR_HOST_URL: ${{ env.SONAR_SERVER_URL }}

src/main/cpp/charsetdecoder.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
* limitations under the License.
1616
*/
1717
#define NOMINMAX /* tell windows not to define min/max macros */
18+
#include <log4cxx/private/string_c11.h>
1819
#include <log4cxx/logstring.h>
1920
#include <log4cxx/helpers/charsetdecoder.h>
2021
#include <log4cxx/helpers/bytebuffer.h>
@@ -585,6 +586,12 @@ CharsetDecoderPtr CharsetDecoder::getDecoder(const LogString& charset)
585586
#endif
586587
}
587588

589+
log4cxx_status_t CharsetDecoder::decode(const char* in, size_t maxByteCount, LogString& out)
590+
{
591+
ByteBuffer buf((char*)in, strnlen_s(in, maxByteCount));
592+
return decode(buf, out);
593+
}
594+
588595

589596

590597

src/main/cpp/defaultconfigurator.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,6 @@ DefaultConfigurator::configureFromFile(const std::vector<LogString>& directories
214214
std::get<0>(result) = ConfigurationStatus::Configured;
215215
return result;
216216
}
217-
LogLog::warn(LOG4CXX_STR("Unable to load: ") + candidate_str);
218217
}
219218
}
220219
}

src/main/cpp/domconfigurator.cpp

Lines changed: 74 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
* See the License for the specific language governing permissions and
1515
* limitations under the License.
1616
*/
17-
#include <log4cxx/private/string_c11.h>
1817
#include <log4cxx/logstring.h>
1918
#include <log4cxx/xml/domconfigurator.h>
2019
#include <log4cxx/appender.h>
@@ -68,6 +67,7 @@ struct DOMConfigurator::DOMConfiguratorPrivate
6867
helpers::Properties props = Configurator::properties();
6968
spi::LoggerRepositoryPtr repository;
7069
spi::LoggerFactoryPtr loggerFactory;
70+
bool appenderAdded{ false };
7171
};
7272

7373
namespace LOG4CXX_NS
@@ -190,9 +190,19 @@ AppenderPtr DOMConfigurator::findAppenderByReference(
190190
apr_xml_doc* doc,
191191
AppenderMap& appenders)
192192
{
193+
AppenderPtr appender;
193194
LogString appenderName(subst(getAttribute(utf8Decoder, appenderRef, REF_ATTR)));
195+
if (appenderName.empty())
196+
{
197+
LogString msg(LOG4CXX_STR("["));
198+
utf8Decoder->decode(appenderRef->name, MAX_ATTRIBUTE_NAME_LEN, msg);
199+
msg += LOG4CXX_STR("] attribute [");
200+
utf8Decoder->decode(REF_ATTR, MAX_ATTRIBUTE_NAME_LEN, msg);
201+
msg += LOG4CXX_STR("] not found");
202+
LogLog::warn(msg);
203+
return appender;
204+
}
194205
AppenderMap::const_iterator match = appenders.find(appenderName);
195-
AppenderPtr appender;
196206

197207
if (match != appenders.end())
198208
{
@@ -311,27 +321,23 @@ AppenderPtr DOMConfigurator::parseAppender(Pool& p,
311321
}
312322
else if (tagName == APPENDER_REF_TAG)
313323
{
314-
LogString refName = subst(getAttribute(utf8Decoder, currentElement, REF_ATTR));
315-
316-
if (!refName.empty() && appender->instanceof(AppenderAttachable::getStaticClass()))
324+
if (appender->instanceof(AppenderAttachable::getStaticClass()))
317325
{
318326
AppenderAttachablePtr aa = LOG4CXX_NS::cast<AppenderAttachable>(appender);
319-
if (LogLog::isDebugEnabled())
327+
if (auto delegateAppender = findAppenderByReference(p, utf8Decoder, currentElement, doc, appenders))
320328
{
321-
LogLog::debug(LOG4CXX_STR("Attaching ") + Appender::getStaticClass().getName()
322-
+ LOG4CXX_STR(" named [") + refName + LOG4CXX_STR("] to ") + Appender::getStaticClass().getName()
323-
+ LOG4CXX_STR(" named [") + appender->getName() + LOG4CXX_STR("]"));
329+
if (LogLog::isDebugEnabled())
330+
{
331+
LogLog::debug(LOG4CXX_STR("Attaching ") + Appender::getStaticClass().getName()
332+
+ LOG4CXX_STR(" named [") + delegateAppender->getName() + LOG4CXX_STR("] to ") + Appender::getStaticClass().getName()
333+
+ LOG4CXX_STR(" named [") + appender->getName() + LOG4CXX_STR("]"));
334+
}
335+
aa->addAppender(delegateAppender);
324336
}
325-
aa->addAppender(findAppenderByReference(p, utf8Decoder, currentElement, doc, appenders));
326-
}
327-
else if (refName.empty())
328-
{
329-
LogLog::error(LOG4CXX_STR("Can't add ") + Appender::getStaticClass().getName() + LOG4CXX_STR(" with empty ref attribute"));
330337
}
331338
else
332339
{
333-
LogLog::error(LOG4CXX_STR("Requesting attachment of ") + Appender::getStaticClass().getName()
334-
+ LOG4CXX_STR(" named [") + refName + LOG4CXX_STR("] to ") + Appender::getStaticClass().getName()
340+
LogLog::error(LOG4CXX_STR("Cannot attach to ") + Appender::getStaticClass().getName()
335341
+ LOG4CXX_STR(" named [") + appender->getName() + LOG4CXX_STR("]")
336342
+ LOG4CXX_STR(" which does not implement ") + AppenderAttachable::getStaticClass().getName());
337343
}
@@ -386,7 +392,8 @@ void DOMConfigurator::parseErrorHandler(Pool& p,
386392
}
387393
else if (tagName == APPENDER_REF_TAG)
388394
{
389-
eh->setBackupAppender(findAppenderByReference(p, utf8Decoder, currentElement, doc, appenders));
395+
if (auto appender = findAppenderByReference(p, utf8Decoder, currentElement, doc, appenders))
396+
eh->setBackupAppender(appender);
390397
}
391398
else if (tagName == LOGGER_REF)
392399
{
@@ -461,7 +468,7 @@ void DOMConfigurator::parseLogger(
461468

462469
if (LogLog::isDebugEnabled())
463470
{
464-
LogLog::debug(LOG4CXX_STR("Retreiving an instance of ") + loggerName);
471+
LogLog::debug(LOG4CXX_STR("Getting [") + loggerName + LOG4CXX_STR("]"));
465472
}
466473
LoggerPtr logger = m_priv->repository->getLogger(loggerName, m_priv->loggerFactory);
467474

@@ -493,7 +500,12 @@ void DOMConfigurator::parseLoggerFactory(
493500

494501
if (className.empty())
495502
{
496-
LogLog::error(LOG4CXX_STR("Logger Factory tag class attribute not found."));
503+
LogString msg(LOG4CXX_STR("["));
504+
utf8Decoder->decode(factoryElement->name, MAX_ATTRIBUTE_NAME_LEN, msg);
505+
msg += LOG4CXX_STR("] attribute [");
506+
utf8Decoder->decode(CLASS_ATTR, MAX_ATTRIBUTE_NAME_LEN, msg);
507+
msg += LOG4CXX_STR("] not found");
508+
LogLog::warn(msg);
497509
}
498510
else
499511
{
@@ -558,25 +570,16 @@ void DOMConfigurator::parseChildrenOfLoggerElement(
558570

559571
if (tagName == APPENDER_REF_TAG)
560572
{
561-
AppenderPtr appender = findAppenderByReference(p, utf8Decoder, currentElement, doc, appenders);
562-
LogString refName = subst(getAttribute(utf8Decoder, currentElement, REF_ATTR));
563-
564-
if (appender)
573+
if (auto appender = findAppenderByReference(p, utf8Decoder, currentElement, doc, appenders))
565574
{
566575
if (LogLog::isDebugEnabled())
567576
{
568577
LogLog::debug(LOG4CXX_STR("Adding ") + Appender::getStaticClass().getName()
569-
+ LOG4CXX_STR(" named [") + refName + LOG4CXX_STR("]")
578+
+ LOG4CXX_STR(" named [") + appender->getName() + LOG4CXX_STR("]")
570579
+ LOG4CXX_STR(" to logger [") + logger->getName() + LOG4CXX_STR("]"));
571580
}
572581
newappenders.push_back(appender);
573582
}
574-
else
575-
{
576-
LogLog::debug(LOG4CXX_STR("Appender named [") + refName +
577-
LOG4CXX_STR("] not found."));
578-
}
579-
580583
}
581584
else if (tagName == LEVEL_TAG)
582585
{
@@ -594,8 +597,10 @@ void DOMConfigurator::parseChildrenOfLoggerElement(
594597
if (newappenders.empty())
595598
logger->removeAllAppenders();
596599
else
600+
{
597601
logger->replaceAppenders(newappenders);
598-
602+
m_priv->appenderAdded = true;
603+
}
599604
propSetter.activate(p);
600605
}
601606

@@ -760,7 +765,7 @@ void DOMConfigurator::parseLevel(
760765
LogString levelStr(subst(getAttribute(utf8Decoder, element, VALUE_ATTR)));
761766
if (LogLog::isDebugEnabled())
762767
{
763-
LogLog::debug(LOG4CXX_STR("Level value for ") + loggerName + LOG4CXX_STR(" is [") + levelStr + LOG4CXX_STR("]"));
768+
LogLog::debug(LOG4CXX_STR("Setting [") + loggerName + LOG4CXX_STR("] level to [") + levelStr + LOG4CXX_STR("]"));
764769
}
765770

766771
if (StringHelper::equalsIgnoreCase(levelStr, LOG4CXX_STR("INHERITED"), LOG4CXX_STR("inherited"))
@@ -815,7 +820,7 @@ void DOMConfigurator::parseLevel(
815820

816821
if (LogLog::isDebugEnabled())
817822
{
818-
LogLog::debug(loggerName + LOG4CXX_STR(" level set to ") +
823+
LogLog::debug(LOG4CXX_STR("[") + loggerName + LOG4CXX_STR("] level is ") +
819824
logger->getEffectiveLevel()->toString());
820825
}
821826
}
@@ -841,7 +846,6 @@ spi::ConfigurationStatus DOMConfigurator::doConfigure
841846
)
842847
{
843848
m_priv->repository = repository ? repository : LogManager::getLoggerRepository();
844-
m_priv->repository->setConfigured(true);
845849

846850
#if LOG4CXX_ABI_VERSION <= 15
847851
m_priv->loggerFactory = std::make_shared<DefaultLoggerFactory>();
@@ -856,15 +860,9 @@ spi::ConfigurationStatus DOMConfigurator::doConfigure
856860

857861
if (rv != APR_SUCCESS)
858862
{
859-
// There is not technically an exception thrown here, but this behavior matches
860-
// what the PropertyConfigurator does
861-
IOException io(rv);
862-
LogString msg2(LOG4CXX_STR("Could not read configuration file ["));
863-
msg2.append(filename.getPath());
864-
msg2.append(LOG4CXX_STR("]. "));
865-
LOG4CXX_DECODE_CHAR(msg, io.what());
866-
msg2.append(msg);
867-
LogLog::error(msg2);
863+
LogLog::error(LOG4CXX_STR("Could not open configuration file [")
864+
+ filename.getPath() + LOG4CXX_STR("]")
865+
, IOException(rv));
868866
return spi::ConfigurationStatus::NotConfigured;
869867
}
870868
else
@@ -874,32 +872,32 @@ spi::ConfigurationStatus DOMConfigurator::doConfigure
874872

875873
if (LogLog::isDebugEnabled())
876874
{
877-
LogString debugMsg = LOG4CXX_STR("Loading configuration file [")
878-
+ filename.getPath() + LOG4CXX_STR("]");
879-
LogLog::debug(debugMsg);
875+
LogLog::debug(LOG4CXX_STR("Loading configuration file [")
876+
+ filename.getPath() + LOG4CXX_STR("]"));
880877
}
881878

882879
rv = apr_xml_parse_file(p.getAPRPool(), &parser, &doc, fd, 2000);
883880

884881
if (rv != APR_SUCCESS)
885882
{
886-
char errbuf[2000];
887-
char errbufXML[2000];
888-
LogString msg2(LOG4CXX_STR("Error parsing file ["));
889-
msg2.append(filename.getPath());
890-
msg2.append(LOG4CXX_STR("], "));
891-
apr_strerror(rv, errbuf, sizeof(errbuf));
892-
LOG4CXX_DECODE_CHAR(lerrbuf, std::string(errbuf));
893-
msg2.append(lerrbuf);
894-
883+
LogString reason;
895884
if (parser)
896885
{
897-
apr_xml_parser_geterror(parser, errbufXML, sizeof(errbufXML));
898-
LOG4CXX_DECODE_CHAR(lerrbufXML, std::string(errbufXML));
899-
msg2.append(lerrbufXML);
886+
char errbuf[2000];
887+
apr_xml_parser_geterror(parser, errbuf, sizeof(errbuf));
888+
LOG4CXX_DECODE_CHAR(lsErrbuf, std::string(errbuf));
889+
reason.append(lsErrbuf);
900890
}
901-
902-
LogLog::error(msg2);
891+
else
892+
{
893+
char errbuf[2000];
894+
apr_strerror(rv, errbuf, sizeof(errbuf));
895+
LOG4CXX_DECODE_CHAR(lsErrbuf, std::string(errbuf));
896+
reason.append(lsErrbuf);
897+
}
898+
LogLog::error(LOG4CXX_STR("Error parsing file [")
899+
+ filename.getPath() + LOG4CXX_STR("]")
900+
, RuntimeException(reason));
903901
return spi::ConfigurationStatus::NotConfigured;
904902
}
905903
else
@@ -910,6 +908,15 @@ spi::ConfigurationStatus DOMConfigurator::doConfigure
910908
}
911909
}
912910

911+
if (!m_priv->appenderAdded)
912+
{
913+
LogLog::warn(LOG4CXX_STR("[") + filename.getPath()
914+
+ LOG4CXX_STR("] did not add an ") + Appender::getStaticClass().getName()
915+
+ LOG4CXX_STR(" to a logger"));
916+
return spi::ConfigurationStatus::NotConfigured;
917+
}
918+
919+
m_priv->repository->setConfigured(true);
913920
return spi::ConfigurationStatus::Configured;
914921
}
915922

@@ -1042,7 +1049,12 @@ void DOMConfigurator::parse(
10421049
}
10431050
else
10441051
{
1045-
LogLog::error(LOG4CXX_STR("DOM element is - not a <configuration> element."));
1052+
LogString msg(LOG4CXX_STR("Root element ["));
1053+
utf8Decoder->decode(element->name, MAX_ATTRIBUTE_NAME_LEN, msg);
1054+
msg += LOG4CXX_STR("] is not [");
1055+
utf8Decoder->decode(CONFIGURATION_TAG, MAX_ATTRIBUTE_NAME_LEN, msg);
1056+
msg += LOG4CXX_STR("]");
1057+
LogLog::error(msg);
10461058
return;
10471059
}
10481060
}
@@ -1163,8 +1175,7 @@ LogString DOMConfigurator::getAttribute(
11631175
{
11641176
if (attrName == attr->name)
11651177
{
1166-
ByteBuffer buf((char*) attr->value, strnlen_s(attr->value, MAX_ATTRIBUTE_NAME_LEN));
1167-
utf8Decoder->decode(buf, attrValue);
1178+
utf8Decoder->decode(attr->value, MAX_ATTRIBUTE_NAME_LEN, attrValue);
11681179
}
11691180
}
11701181

0 commit comments

Comments
 (0)