From 369bad01b8aeae7c76061ac42ca45a9271535eb1 Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones <dceejay@gmail.com>
Date: Fri, 3 Nov 2023 08:55:38 +0000
Subject: [PATCH] check topic length > 0 before publish

to close #4414
---
 .../@node-red/nodes/core/network/10-mqtt.js   | 31 ++++++++++---------
 1 file changed, 16 insertions(+), 15 deletions(-)

diff --git a/packages/node_modules/@node-red/nodes/core/network/10-mqtt.js b/packages/node_modules/@node-red/nodes/core/network/10-mqtt.js
index ce97f613f..a2aed0b03 100644
--- a/packages/node_modules/@node-red/nodes/core/network/10-mqtt.js
+++ b/packages/node_modules/@node-red/nodes/core/network/10-mqtt.js
@@ -104,6 +104,7 @@ module.exports = function(RED) {
      * @returns `true` if it is a valid topic
      */
     function isValidPublishTopic(topic) {
+        if (topic.length === 0) return false;
         return !/[\+#\b\f\n\r\t\v\0]/.test(topic);
     }
 
@@ -219,8 +220,8 @@ module.exports = function(RED) {
      */
     function subscriptionHandler(node, datatype ,topic, payload, packet) {
         const msg = {topic:topic, payload:null, qos:packet.qos, retain:packet.retain};
-        const v5 = (node && node.brokerConn) 
-            ? node.brokerConn.v5() 
+        const v5 = (node && node.brokerConn)
+            ? node.brokerConn.v5()
             : Object.prototype.hasOwnProperty.call(packet, "properties");
         if(v5 && packet.properties) {
             setStrProp(packet.properties, msg, "responseTopic");
@@ -451,7 +452,7 @@ module.exports = function(RED) {
 
     /**
      * Perform the disconnect action
-     * @param {MQTTInNode|MQTTOutNode} node 
+     * @param {MQTTInNode|MQTTOutNode} node
      * @param {Function} done
      */
     function handleDisconnectAction(node, done) {
@@ -865,7 +866,7 @@ module.exports = function(RED) {
              * Call end and wait for the client to end (or timeout)
              * @param {mqtt.MqttClient} client The broker client
              * @param {number} ms The time to wait for the client to end
-             * @returns 
+             * @returns
              */
             let waitEnd = (client, ms) => {
                 return new Promise( (resolve, reject) => {
@@ -905,7 +906,7 @@ module.exports = function(RED) {
         node.subid = 1;
 
         //typedef for subscription object:
-        /** 
+        /**
          * @typedef {Object} Subscription
          * @property {String} topic - topic to subscribe to
          * @property {Object} [options] - options object
@@ -933,7 +934,7 @@ module.exports = function(RED) {
             const ref = _ref || 0;
             let options
             let qos = 1 // default to QoS 1 (AWS and several other brokers don't support QoS 2)
-            
+
             // if options is an object, then clone it
             if (typeof _options == "object") {
                 options = RED.util.cloneMessage(_options || {})
@@ -947,7 +948,7 @@ module.exports = function(RED) {
             if (typeof qos === "number" && qos >= 0 && qos <= 2) {
                 options.qos = qos;
             }
-            
+
             subscription.topic = _topic;
             subscription.qos = qos;
             subscription.options = RED.util.cloneMessage(options);
@@ -957,16 +958,16 @@ module.exports = function(RED) {
         }
 
         /**
-         * If topic is a subscription object, then use that, otherwise look up the topic in 
+         * If topic is a subscription object, then use that, otherwise look up the topic in
          * the  subscriptions object.  If the topic is not found, then create a new subscription
          * object and add it to the subscriptions object.
-         * @param {Subscription|String} topic 
-         * @param {*} options 
-         * @param {*} callback 
-         * @param {*} ref 
+         * @param {Subscription|String} topic
+         * @param {*} options
+         * @param {*} callback
+         * @param {*} ref
          */
         node.subscribe = function (topic, options, callback, ref) {
-            /** @type {Subscription} */ 
+            /** @type {Subscription} */
             let subscription
             let doCompare = false
             let changesFound = false
@@ -1004,7 +1005,7 @@ module.exports = function(RED) {
                     _brokerConn.unsubscribe(sub.topic, sub.ref, true)
                 }
             })
-            
+
             // if subscription is found (or sent in as a parameter), then check for changes.
             // if there are any changes requested, tidy up the old subscription
             if (subscription) {
@@ -1091,7 +1092,7 @@ module.exports = function(RED) {
                         delete sub[ref]
                     }
                 }
-                // if instructed to remove the actual MQTT client subscription 
+                // if instructed to remove the actual MQTT client subscription
                 if (unsub) {
                     // if there are no more subscriptions for the topic, then remove the topic
                     if (Object.keys(sub).length === 0) {