basic/qa/cppunit/test_compiler_checks.cxx |   53 ++++++++++++++++++++++++++++++
 basic/source/comp/scanner.cxx             |   37 ++++++++++++++++----
 2 files changed, 83 insertions(+), 7 deletions(-)

New commits:
commit a400c865a6c9f0185a1986db617ee6fc9dd1861d
Author:     Luv Sharma <luvsharma....@gmail.com>
AuthorDate: Sat Jan 27 14:54:49 2024 +0530
Commit:     Andreas Heinisch <andreas.heini...@yahoo.de>
CommitDate: Mon Apr 22 16:05:53 2024 +0200

    tdf#93727 Syntax Error on # in basic
    
    Change-Id: I400a4061de580a5c91b0e4763cad40ae88a9f738
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162639
    Tested-by: Jenkins
    Tested-by: Andreas Heinisch <andreas.heini...@yahoo.de>
    Reviewed-by: Andreas Heinisch <andreas.heini...@yahoo.de>

diff --git a/basic/qa/cppunit/test_compiler_checks.cxx 
b/basic/qa/cppunit/test_compiler_checks.cxx
index 773719e9fd45..2b8e72997c64 100644
--- a/basic/qa/cppunit/test_compiler_checks.cxx
+++ b/basic/qa/cppunit/test_compiler_checks.cxx
@@ -114,4 +114,57 @@ CPPUNIT_TEST_FIXTURE(CppUnit::TestFixture, 
testTdf149402_vba)
     CPPUNIT_ASSERT(!aMacro.HasError());
 }
 
+CPPUNIT_TEST_FIXTURE(CppUnit::TestFixture, testTdf93727_if)
+{
+    // #If and #End directive
+    MacroSnippet aMacro("Sub doUnitTest
"
+                        "  #If 1 = 1 Then
"
+                        "      Const a = 10
"
+                        "  #End If
"
+                        "End Sub
");
+    aMacro.Compile();
+    CPPUNIT_ASSERT_MESSAGE("#If directive causes compile error", 
!aMacro.HasError());
+}
+
+CPPUNIT_TEST_FIXTURE(CppUnit::TestFixture, testTdf93727_else)
+{
+    // #Else directive
+    MacroSnippet aMacro("Sub doUnitTest
"
+                        "a = 0
"
+                        "#If 1 = 0 Then
"
+                        "    a = 10
"
+                        "#Else
"
+                        "    a = 20
"
+                        "#End If
"
+                        "End Sub
");
+    aMacro.Compile();
+    CPPUNIT_ASSERT_MESSAGE("#Else directive causes compile error", 
!aMacro.HasError());
+}
+
+CPPUNIT_TEST_FIXTURE(CppUnit::TestFixture, testTdf93727_elseif)
+{
+    // #ElseIf directive
+    MacroSnippet aMacro("Sub doUnitTest
"
+                        "a = 0
"
+                        "  #If 1 = 0 Then
"
+                        "      a = 10
"
+                        "  #ElseIf 2 = 2 Then
"
+                        "      a = 20
"
+                        "  #End If
"
+                        "End Sub
");
+    aMacro.Compile();
+    CPPUNIT_ASSERT_MESSAGE("#ElseIf directive causes compile error", 
!aMacro.HasError());
+}
+
+CPPUNIT_TEST_FIXTURE(CppUnit::TestFixture, testTdf93727_const)
+{
+    // #Const directive
+    MacroSnippet aMacro("#Const MaxValue = 1000
"
+                        "Sub doUnitTest
"
+                        "   Dim value As Integer
"
+                        "   value = MaxValue
"
+                        "End Sub
");
+    aMacro.Compile();
+    CPPUNIT_ASSERT_MESSAGE("#Const directive causes compile error", 
!aMacro.HasError());
+}
 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/basic/source/comp/scanner.cxx b/basic/source/comp/scanner.cxx
index 45b65a29b129..820951889ad7 100644
--- a/basic/source/comp/scanner.cxx
+++ b/basic/source/comp/scanner.cxx
@@ -29,6 +29,7 @@
 #include <rtl/character.hxx>
 #include <o3tl/string_view.hxx>
 #include <utility>
+#include <vector>
 
 SbiScanner::SbiScanner(OUString _aBuf, StarBASIC* p)
     : aBuf(std::move(_aBuf))
@@ -209,6 +210,17 @@ bool SbiScanner::readLine()
     return true;
 }
 
+// Function to check if a string is a valid compiler directive
+static bool isValidCompilerDirective(std::u16string_view directive) {
+    static const std::vector<std::u16string_view> validDirectives = {
+        u"if", u"elseif", u"else", u"end", u"const"
+    };
+
+    return std::any_of(validDirectives.begin(), validDirectives.end(), 
[&](const auto& valid) {
+        return o3tl::matchIgnoreAsciiCase(directive, valid);
+    });
+}
+
 bool SbiScanner::NextSym()
 {
     // memorize for the EOLN-case
@@ -220,7 +232,6 @@ bool SbiScanner::NextSym()
     eScanType = SbxVARIANT;
     aSym.clear();
     bHash = bSymbol = bNumber = bSpaces = false;
-    bool bCompilerDirective = false;
 
     // read in line?
     if (nLineIdx == -1)
@@ -256,6 +267,8 @@ bool SbiScanner::NextSym()
     if(nCol < aLine.getLength() && aLine[nCol] == '#')
     {
         sal_Int32 nLineTempIdx = nLineIdx;
+        std::u16string_view candidate(aLine.subView(nCol + 1));
+
         do
         {
             nLineTempIdx++;
@@ -266,9 +279,20 @@ bool SbiScanner::NextSym()
         {
             ++nLineIdx;
             ++nCol;
-            //ignore compiler directives (# is first non-space character)
+            //handle compiler directives (# is first non-space character)
             if (nOldCol2 == 0)
-                bCompilerDirective = true;
+            {
+                if (isValidCompilerDirective(candidate))
+                {
+                    // Skip the whole line if starts with a hash and is a 
valid compiler directive
+                    nCol = 0;
+                    goto eoln;
+                }
+                else
+                {
+                    GenError(ERRCODE_BASIC_SYNTAX);
+                }
+            }
             else
                 bHash = true;
         }
@@ -660,10 +684,9 @@ bool SbiScanner::NextSym()
 
 PrevLineCommentLbl:
 
-    if( bPrevLineExtentsComment || (eScanType != SbxSTRING &&
-                                    ( bCompilerDirective ||
-                                      aSym.startsWith("'") ||
-                                      aSym.equalsIgnoreAsciiCase( "REM" ) ) ) )
+    if (bPrevLineExtentsComment ||
+        (eScanType != SbxSTRING &&
+        (aSym.startsWith("'") || aSym.equalsIgnoreAsciiCase("REM") || 
aSym.startsWith("#"))))
     {
         bPrevLineExtentsComment = false;
         aSym = "REM";

Reply via email to