Fortify 掃描發生 java.lang.OutOfMemoryError: GC overhead limit exceeded,代表 JVM 記憶體 Heap 空間不足,且垃圾回收(GC)耗費超過 98% 的時間卻只能回收不到 2% 的記憶體。堆疊訊息顯示 Fortify 在解析 PHP 的 hereDoc (Heredoc語法) 時耗盡了記憶體。
請依序嘗試以下解決方案:
1. 增加 Fortify 掃描的記憶體上限
預設的記憶體設定可能不足以處理大型專案或複雜的 PHP 檔案。可以在執行 sourceanalyzer 命令行中加入 -Xmx 參數來提高記憶體配額:
命令列執行 (CLI):
sourceanalyzer -b <build_id> -Xmx16G -scan -f result.fpr
(可依你的伺服器硬體規格調整,例如 -Xmx12G 或 -Xmx24G)
若使用 GUI (Audit Workbench / ScanWizard):
開啟 Fortify Audit Workbench。
進入 Options > Global Settings > Memory Options。
將 Maximum Allocation (-Xmx) 調大(如 16384 MB)。
修改全域設定檔 (fortify-sca.properties):
找到 Fortify 安裝目錄或使用者目錄下的設定檔(例如 <Fortify_Home>/Core/config/fortify-sca.properties),修改或加入以下參數:
com.fortify.sca.ProjectScanMemoryMB=16384
2. 排除不必要的檔案或大型自動生成檔
從錯誤堆疊可看出問題出在解析 PHP 的 hereDoc 語法(可能是巨大的模板檔、自動生成的 SQL/Data 檔、或是包含大字串陣列的檔案)。
如果增加記憶體後仍失敗,建議排除非必要的第三方套件與靜態檔:
在翻譯(Translation)階段使用 -exclude 排除特定目錄或檔案:
sourceanalyzer -b <build_id> -exclude "/vendor/" -exclude "/node_modules/" -exclude "/*.min.js" src/
過濾大檔案:
可以在 fortify-sca.properties 中限制 Fortify 解析單一檔案的大小上限:
com.fortify.sca.limit.file.size=10240
(單位為 KB,例如設定 10240 會跳過大於 10MB 的單一原始碼檔案)
3. 採用「雙階段掃描」分離記憶體開銷
若原本是單一指令執行,請改為將翻譯 (Translation)與掃描 (Scan)拆為兩個獨立步驟,並只在掃描階段調大記憶體:
# 第一步:翻譯階段
sourceanalyzer -b myproject -clean
sourceanalyzer -b myproject ./src
# 第二步:分析掃描階段 (在此處給予最大記憶體)
sourceanalyzer -b myproject -Xmx16G -scan -f result.fpr
建議處理順序
- 直接將記憶體調大至 16G (
-Xmx16G) 重試一次。 - 若依然爆記憶體,檢查專案中是否有包含大量文字資料的
.php檔案(如大陣列檔、DB dump 檔、巨型 Heredoc 模板),並使用-exclude將其排除。
detail error message:
[error]: There is not enough memory available to complete analysis. For details on making more memory available, please consult the user manual.
java.lang.OutOfMemoryError: GC overhead limit exceeded
at com.fortify.frontend.php.parser.PHPLexerBase.nextToken(PHPLexerBase.java:95) ~[?:?]
at org.antlr.v4.runtime.BufferedTokenStream.fetch(BufferedTokenStream.java:169) ~[antlr4-runtime-4.13.1.jar:4.13.1]
at org.antlr.v4.runtime.BufferedTokenStream.sync(BufferedTokenStream.java:152) ~[antlr4-runtime-4.13.1.jar:4.13.1]
at org.antlr.v4.runtime.BufferedTokenStream.nextTokenOnChannel(BufferedTokenStream.java:325) ~[antlr4-runtime-4.13.1.jar:4.13.1]
at org.antlr.v4.runtime.CommonTokenStream.adjustSeekIndex(CommonTokenStream.java:70) ~[antlr4-runtime-4.13.1.jar:4.13.1]
at org.antlr.v4.runtime.BufferedTokenStream.consume(BufferedTokenStream.java:137) ~[antlr4-runtime-4.13.1.jar:4.13.1]
at org.antlr.v4.runtime.Parser.consume(Parser.java:571) ~[antlr4-runtime-4.13.1.jar:4.13.1]
at org.antlr.v4.runtime.Parser.match(Parser.java:205) ~[antlr4-runtime-4.13.1.jar:4.13.1]
at com.fortify.frontend.php.parser.PHPParser.hereDocPart(PHPParser.java:9032) ~[?:?]
at com.fortify.frontend.php.parser.PHPParser.hereDocExpr(PHPParser.java:8947) ~[?:?]
at com.fortify.frontend.php.parser.PHPParser.primaryExpr(PHPParser.java:9230) ~[?:?]
at com.fortify.frontend.php.parser.PHPParser.exponentExpr(PHPParser.java:8627) ~[?:?]
at com.fortify.frontend.php.parser.PHPParser.unaryExpr(PHPParser.java:8571) ~[?:?]
at com.fortify.frontend.php.parser.PHPParser.instanceofExpr(PHPParser.java:8470) ~[?:?]
at com.fortify.frontend.php.parser.PHPParser.notExpr(PHPParser.java:8412) ~[?:?]
at com.fortify.frontend.php.parser.PHPParser.productExpr(PHPParser.java:8321) ~[?:?]
at com.fortify.frontend.php.parser.PHPParser.sumExpr(PHPParser.java:8222) ~[?:?]
at com.fortify.frontend.php.parser.PHPParser.shiftExpr(PHPParser.java:8123) ~[?:?]
at com.fortify.frontend.php.parser.PHPParser.comparisonExpr(PHPParser.java:8037) ~[?:?]
at com.fortify.frontend.php.parser.PHPParser.equalityExpr(PHPParser.java:7960) ~[?:?]
at com.fortify.frontend.php.parser.PHPParser.bitwiseAndExpr(PHPParser.java:7883) ~[?:?]
at com.fortify.frontend.php.parser.PHPParser.bitwiseXorExpr(PHPParser.java:7805) ~[?:?]
at com.fortify.frontend.php.parser.PHPParser.bitwiseOrExpr(PHPParser.java:7727) ~[?:?]
at com.fortify.frontend.php.parser.PHPParser.booleanAndExpr(PHPParser.java:7649) ~[?:?]
at com.fortify.frontend.php.parser.PHPParser.booleanOrExpr(PHPParser.java:7571) ~[?:?]
at com.fortify.frontend.php.parser.PHPParser.nullCoalescingExpr(PHPParser.java:7501) ~[?:?]
at com.fortify.frontend.php.parser.PHPParser.ternaryExpr(PHPParser.java:7426) ~[?:?]
at com.fortify.frontend.php.parser.PHPParser.assignExpr(PHPParser.java:9557) ~[?:?]
at com.fortify.frontend.php.parser.PHPParser.primaryExpr(PHPParser.java:9276) ~[?:?]
at com.fortify.frontend.php.parser.PHPParser.exponentExpr(PHPParser.java:8627) ~[?:?]
at com.fortify.frontend.php.parser.PHPParser.unaryExpr(PHPParser.java:8571) ~[?:?]
at com.fortify.frontend.php.parser.PHPParser.instanceofExpr(PHPParser.java:8470) ~[?:?]
這兩個問題解答如下:
第一題:Bash 命令列上的 myproject 存在哪裡?
在 Fortify 命令列中:
sourceanalyzer -b myproject -clean
sourceanalyzer -b myproject ./src
sourceanalyzer -b myproject -scan -f result.fpr
-b myproject 中的 myproject 稱為 Build ID(建置識別碼)。
它不是一個真實的專案資料夾名稱,而是 Fortify 在系統內部用來記錄「翻譯(Translation)階段抽取的原始碼 AST 語法樹與中間檔」的暫存標籤。
1. 實際檔案存在哪裡?
Fortify 會將 myproject 的中間檔案儲存在使用者家目錄下的 Fortify SCA 暫存區:
- Linux / macOS:
~/.fortify/sca<版本號>/build/myproject/ - Windows (PowerShell / CMD):
C:\Users\<帳號>\.fortify\sca<版本號>\build\myproject\
2. 注意事項
- 執行
-clean時(如sourceanalyzer -b myproject -clean),Fortify 就會刪除這個路徑下名為myproject的暫存資料夾。 - 在同一次掃描任務中,Translation(翻譯)和 Scan(分析)必須使用完全相同的 Build ID。
第二題:如何匯出 DeveloperWorkbook PDF 報告?
Fortify 提供了一個專門的命令行報表工具 ReportGenerator,可以直接讀取掃描結果檔(.fpr)並套用 DeveloperWorkbook 範本產生 PDF 報告。
1. 匯出命令(Command-line)
請在 Terminal / Command Prompt 執行:
ReportGenerator -format pdf -f DeveloperWorkbook.pdf -source result.fpr -template DeveloperWorkbook.xml
2. 參數說明
-format pdf:指定輸出格式為 PDF(亦支援rtf)。-f DeveloperWorkbook.pdf:輸出的 PDF 檔案名稱。-source result.fpr:你前面掃描完成所產生的.fpr結果檔。-template DeveloperWorkbook.xml:指定使用研發團隊常用的 Developer Workbook 報表範本。
3. 補充技巧 (進階)
如果是系統找不到 DeveloperWorkbook.xml:請加上完整的範本路徑,預設位在 Fortify 安裝目錄下:
# Linux / macOS
ReportGenerator -format pdf -f DeveloperWorkbook.pdf -source result.fpr -template /opt/Fortify/Core/config/reports/DeveloperWorkbook.xml
# Windows
ReportGenerator -format pdf -f DeveloperWorkbook.pdf -source result.fpr -template "C:\Program Files\Fortify\Core\config\reports\DeveloperWorkbook.xml"
如果報告顯示的弱點數量被限制(例如預設只印前 5 個):可以將 DeveloperWorkbook.xml 複製一份出來,用文字編輯器開啟,搜尋 limit="5" 並將其修改為 limit="-1"(代表不限數量,印出全部),再將修改後的 XML 作為 -template 帶入即可。
翻譯(Translation)階段需要限制 memory usage?
答案是需要。
雖然 Fortify 官方文件常強調在「分析(Scan)」階段給予大記憶體,但翻譯(Translation)階段如果記憶體不足,同樣會直接發生 OutOfMemoryError 或導致解析中斷(Crash)。
特別是你的案例中有大型 PHP 檔案(帶有巨型 Heredoc 語法),Fortify 在 Translation 階段進行語法解析(Lexing/Parsing)並建構 AST(抽象語法樹)時,就會在記憶體中吃掉大量空間。
1. 為什麼 Translation 階段也需要限制/調大記憶體?
- 語法分析(AST 建構): 翻譯階段並非只是「複製檔案」,而是將原始碼編譯成 Fortify 的內部中間語言(NST/AST)。遇到複雜的 PHP 樣板、巨型 JSON/SQL 字串或第三方套件時,記憶體開銷會瞬間衝高。
- 預設記憶體通常太小: 若未手動指定,
-b翻譯階段會使用 Fortify 的預設配額(通常僅 1GB~2GB),極易觸發java.lang.OutOfMemoryError: GC overhead limit exceeded。
2. 如何在 Translation 階段設定記憶體?
語法與 Scan 階段完全相同,直接在 sourceanalyzer 命令列加上 -Xmx 參數:
# 1. 先清除舊的 Build ID 暫存
sourceanalyzer -b myproject -clean
# 2. 【Translation 階段】給予足夠的記憶體(例如 16G)
sourceanalyzer -b myproject -Xmx16G ./src
# 3. 【Scan 階段】同樣給予足夠的記憶體
sourceanalyzer -b myproject -Xmx16G -scan -f result.fpr
3. Translation 階段記憶體優化的最佳做法
如果給了 -Xmx16G 在 Translation 階段依然記憶體溢位,請搭配以下優化策略:
主動過濾不需翻譯的目錄(最有效):不要將非業務邏輯的套件帶入 Translation 階段:
sourceanalyzer -b myproject -Xmx16G \ -exclude "/vendor/" \ -exclude "/node_modules/" \ -exclude "/*.min.js" \ ./src
設定單一檔案大小上限(全域設定):在 fortify-sca.properties 設定檔中加上 limit,防止 Translation 階段去解析幾十 MB 的巨型檔案:
com.fortify.sca.limit.file.size=10240
全域預設記憶體配置:若不想每次命令列都打 -Xmx,可在 fortify-sca.properties 中調整全域預設值,這會同時作用於 Translation 與 Scan 階段:
com.fortify.sca.ProjectTranslationMemoryMB=16384
com.fortify.sca.ProjectScanMemoryMB=16384
要匯出符合 OWASP Top 10 安全標準的 PDF 報告,選取的範本(Template)檔案說明如下:
1. 建議選擇的 Template 檔案
Fortify 官方內建了不同年份版本的 OWASP Top 10 報本 XML 檔,位於 Fortify 報表目錄中:
| 範本檔名 (Template File) | 適用 OWASP 版本 | 說明 / 適用場景 |
OWASP Top 10 2021.xml | OWASP Top 10 (2021) | 【最推薦】 目前最主流的官方標準版本,建議優先選用。 |
OWASP Top 10 2017.xml | OWASP Top 10 (2017) | 適用於客戶或公司稽核規範明確指定 2017 年版的專案。 |
OWASP Top 10.xml | 通用/預設連結版 | 部分 Fortify 舊版本的預設檔名(會指向該版本的預設 OWASP)。 |
2. 命令行 (ReportGenerator) 執行指令
預設範本檔案存放在 Fortify 安裝目錄下的 Core/config/reports/ 資料夾中。
Linux / macOS:
ReportGenerator -format pdf \
-f OWASP_Top10_Report.pdf \
-source result.fpr \
-template "/opt/Fortify/Core/config/reports/OWASP Top 10 2021.xml"
Windows:
ReportGenerator -format pdf ^
-f OWASP_Top10_Report.pdf ^
-source result.fpr ^
-template "C:\Program Files\Fortify\Core\config\reports\OWASP Top 10 2021.xml"
(注意:路徑中包含空白字元,必須使用雙引號 "..." 包裹)
3. 在 Audit Workbench (GUI) 中選擇
若使用圖形化介面匯出:
- 開啟
.fpr結果檔。 - 點擊選單 Tools > Generate Report。
- 在 Report Template 下拉選單中選擇
OWASP Top 10 2021(或OWASP Top 10)。 - 將 Format 設為 PDF,點擊 Save Report 即可。
💡 關鍵技巧:印出「所有」弱點細節 (解除預設 5 筆限制)
Fortify 官方預設的 OWASP 範本為了控制 PDF 頁數,預設每個漏洞分類只會列出前 5 筆弱點細節 (limit="5")。
若你的報告需要列出全部弱點:
- 將
OWASP Top 10 2021.xml複製到你的工作目錄,改名為OWASP_Custom.xml。 - 用文字編輯器打開它,將裡面的
limit="5"全部覆蓋替換為limit="-1"(-1代表不限制數量)。 - 執行指令時帶入
-template OWASP_Custom.xml即可印出完整清單。
command line manual:
sourceanalyzer --help
OpenText SAST (Fortify) CE 25.2.0.0116
Copyright (c) 2003-2025 Open Text
Usage:
Clean:
sourceanalyzer.exe -b <build-id> -clean
Build:
sourceanalyzer.exe -b <build-id> <sca-build-opts>
Scan:
sourceanalyzer.exe -b <build-id> -scan <sca-scan-opts>
Detailed invocation:
Build:
sourceanalyzer.exe -b <build-id>
[ <sca-build-options> ]
<file-specifier>
sourceanalyzer.exe -b <build-id>
[ <sca-build-options> ]
<compiler> <compiler-options>
sourceanalyzer.exe -b <build-id>
[ <sca-build-options> ]
touchless <build-tool> [ <build-tool-options> ]
sourceanalyzer.exe -b <build-id>
[ <sca-build-options> ]
devenv <solution-file> /REBUILD
sourceanalyzer.exe -b <build-id>
[ <sca-build-options> ]
msbuild /t:rebuild <solution-or-project-file>
sourceanalyzer.exe -b <build-id>
[ <sca-build-options> ]
xcodebuild -project <xcodeproj-file>
sourceanalyzer.exe -b mybuild
-source-base-dir <webapp-root> <cfm-file-specifier>
Scan:
sourceanalyzer.exe -b <build-id> -scan
[ -f <output-file> ]
[ -scan-precision <level> ]
[ -rules <rules.xml> [ -no-default-rules ] ]
[ -filter <filter-file> ]
Clean:
sourceanalyzer.exe -b <build-id> -clean
Query:
sourceanalyzer.exe -b <build-id> { -show-build-warnings | -show-files }
sourceanalyzer.exe { -version | -show-build-ids }
sourceanalyzer.exe { -h | -? | -help }
Options
General Options
These options are applicable to all sourceanalyzer.exe invocations.
@<file> Reads command line options from the specified
file. Note that there is no space before the
file argument.
-debug Causes the build step to write additional
troubleshooting information to the log file.
Use if instructed by Fortify Customer Support.
Also see "-logfile".
-logfile <file> Specifies a destination for the log file.
-verbose Outputs verbose messages to the console.
-Xmx<num>M Specifies the maximum Java heap size.
Default is -Xmx1800M.
-autoheap Instructs SCA to set the maximum Java heap size
based on available physical memory. Use instead
of -Xmx. Enabled by default.
-fcontainer When run in a Docker container, instructs SCA
to detect and use only the memory allocated to
the container.
-version Shows the sourceanalyzer.exe version.
Command Options
Note: Only one "command" option is allowed per invocation.
-h Displays this help text.
-help
-?
-clean Deletes all intermediate files and build records.
When a build ID is also specified with -b, only
files and build records related to that build ID
are deleted.
-show-binaries See the user guide.
-show-build-tree See the user guide.
-show-build-ids Lists all the Fortify build IDs (analysis models).
-show-build-warnings Displays all the actionable warnings that
occurred during the translation phase of the build
ID specified by "-b".
-show-files Displays all the source files built into the model
specified by "-b".
-show-loc Displays lines of code processed for files built
into the model specified by "-b".
-scan Causes sourceanalyzer.exe to run an analysis.
(none) If no command option is present, a build step
is assumed.
Build Options
"Build" options translate source code into a Fortify analysis model.
-b <build-id> Specifies a unique name that identifies the
Fortify analysis model to be built. Also see
"-scan".
-build-label <label> Specifies an optional, arbitrary string value to
the Fortify analysis model. Will be included in
the output file.
-build-project <project> Specifies an optional, arbitrary string value to
the Fortify analysis model. Will be included in
the output file.
-build-version <version> Specifies an optional, arbitrary string value to
the Fortify analysis model. Will be included in
the output file.
-encoding <encoding-name> Specifies the source file encoding.
Default value is the platform default.
Compiler Integration Build Options
These options are used when integrating OpenText SAST (Fortify) with a compiler.
<compiler> <compiler-opts> Specifies the compiler command line. The file
being compiled will be added to the analysis
model, and the compiler will be invoked.
touchless <build-tool> Specifies a build tool command. The build tool
[ <build-tool-options> ] will be invoked, and any file being compiled
will be added to the analysis model.
-nc When specified, the compiler is not invoked.
File Specification Build Options
These options are used to pass source files directly to OpenText SAST (Fortify).
<file-specifier> Expression denoting a file or a group of files,
optionally matching a pattern:
file1.java - a file
file*.java - files matching expression
"path/**/*.java" - recursive expression matches.
Note: Always escape ** expressions in quotes.
-exclude <file-specifier> Excludes any files matched by <file-specifier>
from the set of files to translate
Java-specific Build Options
These options should be used in conjunction with file specification options.
-classpath <classpath> Uses the specified classpath value for Java
-cp <classpath> builds.
-extdirs Accepts a colon or semicolon separated list
of directories. Any jar files found in
these directories are included on the
classpath. Equivalent to the -extdirs option
to javac.
-sourcepath Specifies the location of source files which will
not be included in the scan but will be used for
name resolution. Equivalent to the -sourcepath
option to javac.
The sourcepath is like classpath, except it uses
source files rather than class files for
resolution.
-source <value> Indicates which version of the Java language the Java
-jdk <value> code adheres to. Valid values are 1.8, 8, 11, 17, 21.
Default is "11".
-java-build-dir <dir> Used to specify one or more directories to which
Java sources are being compiled. May also be
specified at scan time.
Other Language-Specific Build Options
-source-base-dir <root> The base directory for a ColdFusion application.
-python-path Add an import directory for a Python application.
-apex Set ".cls" file extension to Apex language.
(detected based on file content by default). Equivalent to
-Dcom.fortify.sca.fileextensions.cls=APEX
-apex-sobject-path Add file to load SObject types in Apex application.
Scan Options
-b <build-id> Specifies the build ID. The build ID is used
to track which files are compiled and linked
as part of a build, to later scan those files.
This option may be specified more than once to
include multiple build IDs in the same scan.
-bin <binary> All source files compiled and linked into the
specified binary are scanned. Multiple binaries
may be specified.
-disable-default-rule-type See the user guide.
-f <file> The file to which analysis results are written.
Default is stdout.
-filter <file> Specifies a filter file. For more information,
see the user guide.
-scan-policy <policy> Specifies a scan policy for vulnerability prioritization.
Valid values are classic, security, devops. Default is security.
For more information, see the user guide.
-java-build-dir <dir> Used to specify one or more directories to which
Java sources have been compiled. May also be
specified at build time.
-no-default-issue-rules See the user guide.
-no-default-sink-rules See the user guide.
-no-default-source-rules See the user guide.
-no-default-rules Indicates that OpenText SAST (Fortify) should not use its
default rules. Must be used in conjunction with
"-rules"
-rules <specifier> Specifies custom rules file or directory. If a
directory is specified, all files ending in ".bin"
or ".xml" are included.
This option may be used multiple times.
-quick Runs a quick scan. Quick scans complete faster at
the cost of reduced accuracy.
-scan-precision <level> Configures the depth, precision and speed of the scan
-p <level> with configuration properties specific for the level.
The valid values are 1, 2, 3, and 4.
-quiet Disables the command line progress bar.
-scan Causes OpenText SAST (Fortify) to perform analysis against a
model. The model must be specified with "-b".
Build Sessions
-export-build-session <file.mbs>
Store the translated model specified by -b to the
specified file.
-import-build-session <file.mbs>
Load the specified file into a build model. If
the build ID of the model already exists in the
model registry, the import fails with the message
that a build already exists with that ID.
License Directives
-store-license-pool-credentials "<lim_url>|<lim_pool_name>|<lim_pool_pwd>|<proxy_url>|<proxy_user>|<proxy_pwd>"
Stores your LIM license pool credentials to
allow OpenText SAST (Fortify) to use the
LIM for licensing. Proxy information is optional.
-clear-license-pool-credentials
Removes the LIM license pool credentials from
the fortify-sca.properties file.
-request-detached-lease <duration>
Requests a detached lease from the LIM license
pool for exclusive use on this system for the
specified duration (in minutes).
-release-detached-lease
Releases a detached lease back to the license
pool.
EXAMPLES
Build examples:
Generic (Java, configuration, PHP, JavaScript, ASP/VBScript, VB6):
sourceanalyzer.exe -b mybuild .
sourceanalyzer.exe -b mybuild file1.java file2.java
sourceanalyzer.exe -b mybuild *.bas *.cls *.frm
sourceanalyzer.exe -b mybuild "site/**/*.php"
ColdFusion translation:
sourceanalyzer.exe -b mybuild -source-base-dir /www/app "/www/app/**/*.cfm"
SQL translation:
sourceanalyzer.exe -b mybuild -Dcom.fortify.sca.fileextensions.sql=PLSQL *.sql
sourceanalyzer.exe -b mybuild -Dcom.fortify.sca.fileextensions.sql=TSQL *.sql
C/C++ builds:
sourceanalyzer.exe -b mybuild gcc -c test.c
sourceanalyzer.exe -b mybuild CL.EXE /o HelloWorld HelloWorld.c
sourceanalyzer.exe -b mybuild make
sourceanalyzer.exe -b mybuild devenv myproject.msproj /REBUILD
Objective-C/C++ builds:
sourceanalyzer.exe -b mybuild clang -ObjC HelloWorld.m
sourceanalyzer.exe -b mybuild xcodebuild -project myproject.xcodeproj
.NET builds:
sourceanalyzer.exe -b mybuild devenv myproj.sln /REBUILD
sourceanalyzer.exe -b mybuild msbuild /t:rebuild myproj.csproj
Java specific builds:
sourceanalyzer.exe -b mybuild -cp lib/dependency.jar "src/**/*.java"
sourceanalyzer.exe -b mybuild -cp mytaglibs.jar webapp/*.jsp
sourceanalyzer.exe -b mybuild touchless ant
J2EE specific builds:
sourceanalyzer.exe -b mybuild -cp "app/WEB-INF/lib/*.jar" app/*.jsp
Scan step:
sourceanalyzer.exe -b mybuild -scan -f results.fpr
See OpenText(TM) Static Application Security Testing (Fortify) User Guide for a complete explanation of each option.
You can open a support case for Fortify products online using
our customer support system. This streamlined procedure is designed to
provide easier access and improved customer satisfaction.
Access your account at https://softwaresupport.softwaregrp.com/.
這代表即使給了 32G 記憶體,ANTLR 在解析 PHP 語法時仍陷入了死迴圈或極度消耗記憶體的狀態(問題依然卡在 PHPParser.hereDocPart / PHPLexerBase)。
通常這有兩個主因:
- Windows 通配符問題:
-exclude "/vendor/"在 CMD/PowerShell 根本沒有生效,Fortify 依然把vendor進去了。 - 存在「超大檔」或「極長 Heredoc 檔」:例如大型 SQL dump、Base64 圖片檔、自動生成的測試資料或超大樣板檔,導致 ANTLR Parser 記憶體暴增。
請依序透過以下方法徹底解決:
1. 修正 Windows 的 -exclude 語法(最常踩坑)
在 Windows 命令列,-exclude必須使用雙引號,且建議使用 ** (Ant 語法) 與 Windows 反斜線,否則過濾會無效:
DOS
sourceanalyzer -b portal_project -clean
sourceanalyzer -b portal_project -Xmx32G -exclude "**/vendor/**" -exclude "**/node_modules/**" -exclude "**/*.min.js" backend/
2. 開啟弱點檔大小限制 (Limit File Size)
這是解決 hereDoc 爆記憶體最有效的武器。直接限制 Fortify 跳過單檔超過指定大小的檔案(例如 1MB 或 2MB):
做法 A:命令列加上 -D 參數
DOS
sourceanalyzer -b portal_project -Xmx32G -Dcom.fortify.sca.limit.file.size=2048 -exclude "**/vendor/**" backend/
( 2048 代表超過 2MB 的原始碼檔案就跳過不安裝/解析,可有效避免吃到包含巨大字串或 Heredoc 的 PHP 檔案)
做法 B:修改 fortify-sca.properties
在 C:\Users\<你的帳號>\.fortify\fortify-sca.properties 或 Fortify 安裝目錄下的 Core\config\fortify-sca.properties 加入:
Properties
com.fortify.sca.limit.file.size=2048
3. 找出到底是哪個「元凶檔案」卡住,單獨排除它
如果是業務邏輯資料夾內有一個幾十 MB 的 PHP 檔案(例如包含超大字串陣列或字典):
請加上 -debug 或 -verbose 參數重新執行一次,並觀察 log 印到哪一個 .php 檔案時卡死:
DOS
sourceanalyzer -b portal_project -Xmx32G -verbose backend/ > scan_log.txt
打開 scan_log.txt 翻到最底端,查看崩潰前最後進行解析(Parsing/Lexing)的是哪一個 .php 檔案,接著直接將該檔案加入排除:
DOS
sourceanalyzer -b portal_project -Xmx32G -exclude "**/ProblematicFile.php" backend/
4. (終極方案)調整 ANTLR / PHP 語法分析設定
如果特定 PHP 檔案無法排除,但包含極長的 Heredoc,可以在 fortify-sca.properties 加入以下參數,限制語法樹深度或停用部分 ANTLR 耗效能的檢查:
# 限制 Fortify 對單一檔案最大解析時間(單位:秒,預設無限制,可設為 300 秒)
com.fortify.sca.PhaseTimeout=300
# 關閉部分過度深度的 AST 解析
com.fortify.sca.DisablePHP2MethodCallDataflow=true
建議嘗試步驟:
- 先執行
sourceanalyzer -b portal_project -clean清除快取。 - 加上限制檔案大小參數
-Dcom.fortify.sca.limit.file.size=2048並修正過濾語法-exclude "**/vendor/**"重新執行。
從你提供的完整 log 可以精準定位出問題的根源所在:
Log 在處理到 SendForgotPasswordTotpApi.php(或緊隨其後的下一個 PHP 檔)時,Fortify 的 PHP 語法解析器 (PHPFrontEnd) 因為遇到極長或結構極度複雜的 Heredoc / String,導致 ANTLR 語法分析器陷入計算迴圈並爆記憶體崩潰,進而拋出 NullPointerException。
請採用以下 4 步驟解決方案 來繞過這個解析器的死區:
步驟 1:強制限制單檔大小 (File Size Limit)
這是最快且最有效的方法。加載此參數能直接讓 Fortify 跳過過大或包含巨大字串 (Heredoc/Blob) 的單一原始碼檔案,避免 ANTLR 解析器卡死。
在 command 加入 -Dcom.fortify.sca.limit.file.size=2048(單位為 KB,即 2MB):
DOS
sourceanalyzer -b portal_backend -clean
sourceanalyzer -b portal_backend -Xmx32G -Dcom.fortify.sca.limit.file.size=2048 backend/
步驟 2:明確排除 TestTools 或測試/資料庫備份檔案
從 Log 中可以看到你的 backend/ 下包含了 TestTools 與 db/migrations。通常測試工具與 Migration 檔中會含有大量假資料、巨型 SQL 字串或 Heredoc 模板。
請使用 Windows 專用 Ant 通配符 將它們排除:
DOS
sourceanalyzer -b portal_backend -clean
sourceanalyzer -b portal_backend -Xmx32G -Dcom.fortify.sca.limit.file.size=2048 -exclude "**/TestTools/**" -exclude "**/db/**" -exclude "**/vendor/**" backend/
步驟 3:定位「致命檔案」並直接單獨排除
如果前兩步執行後依然在 SendForgotPasswordTotpApi.php 附近崩潰,代表問題出在業務邏輯程式碼本身的某個特定檔案。
- 打開
SendForgotPasswordTotpApi.php以及與它在同一目錄下的前後檔案。 - 檢查程式碼中是否有使用
<<<EOD“/SendForgotPasswordTotpApi.php” “/TestTools/” “/db/” “/vendor/” # ### (2048 (5分鐘),防止 Heredoc — -Dcom.fortify.sca.limit.file.size=”2048″ -Xmx32G -b -clean -exclude -f -scan / 2MB 3. 300 4:寫入 ANTLR Fortify HTML KB) Nowdoc PHP Phase Timeout,讓-exclude<<<HTMLC:\Users\max\.fortify\fortify-sca.propertiescmd “`propertiesfortify-sca.propertiesbackend/ com.fortify.sca.PhaseTimeout=”300″ com.fortify.sca.limit.file.size=”2048″ portal_backend portal_backend_result.fpr sourceanalyzer 之類的 在檔案末端寫入以下設定: 完成上述設定後,執行以下完整的標準清洗與翻譯流程: 將它單獨排除: 建議的標準執行指令 或 找到該檔案後,直接使用 檔案也發生 步驟 無限迴圈 秒 若要避免以後其他 解析單一檔案逾時自動跳過,而不是直接崩潰: 設定全域超時(終極防護) 設定單一階段解析超時為 語法,且裡面放了極長的 語法卡死,直接開啟 請開啟以下檔案(若沒有請自行建立): 資料或密碼學金鑰/雜湊值。 郵件模板、JSON 限制單一檔案解析上限>
這個檔案 (SendForgotPasswordTotpApi.php) 正是導致 Fortify ANTLR 語法分析器崩潰爆記憶體的元凶。
為什麼是這個檔案?
- 使用了巨大的
Heredoc($htmlBody = <<<EOD ### #### $htmlBody="str_replace('{$totpCode}'," $htmlTemplate="file_get_contents($templatePath);" $htmlTemplate); $templatePath="__DIR__" $totpCode, '/../../templates/emails/forgot_password_totp.html'; (Inline) (圖案樣式)、HTML **ANTLR **修改後的 --- . ... / // 2. 25.2 <<<EOD A:重構此 Base64 CSS、內嵌 Data EOD; EOD;): Fortify GC HTML Heredoc PHP SVG URI$htmlBody$textBody.blade.php.htmlHeredocPHPLexerBasePHPParser.hereDocPart\、雙引號、SVG phpjava.lang.OutOfMemoryError: exceeded。 limit overhead 使用的 使用簡單的字串替換填入動態變數 在處理包含複雜字元(如反斜線 字串。 將 將原本巨大的 抽離至獨立的 方案 時,內部的詞法狀態轉換會陷入計算遞迴,進而導致 替換為讀取外部模板檔案: 標籤的巨型 模板抽離,這同時也能讓你的程式碼結構更乾淨。 模板檔案中,改用檔案讀取方式載入: 檔案(最推薦,一勞永逸) 的 的內聯 程式碼: 與 解析器缺陷: 解決方案:重構此檔案(推薦)或針對性排除 語法)的長 這個檔案裡包含了一整段包含 這有兩種解決方式,最根本的方法是重構程式碼,將> 優勢:抽離後 Fortify 解析這個.php時就不會觸發 Heredoc 的 ANTLR 解析 Bug,掃描能順利通過,且不會遺漏該 API 的安全弱點分析!
方案 B:單獨排除此檔案(最快)
如果你目前不想改動原始碼,可以在執行命令時,直接將該檔案單獨排除掉:
sourceanalyzer -b portal_backend -clean
sourceanalyzer -b portal_backend -Xmx16G -Dcom.fortify.sca.limit.file.size=2048 -exclude "**/SendForgotPasswordTotpApi.php" -exclude "**/TestTools/**" -exclude "**/db/**" -exclude "**/vendor/**" backend/
方案 C:將檔案大小限制調低
因為這個 .php 檔案因為包含巨型 HTML,檔案大小可能較大。你可以嘗試將檔案限制從 2048 (2MB) 調小到 100 (100KB):
sourceanalyzer -b portal_backend -clean
sourceanalyzer -b portal_backend -Xmx16G -Dcom.fortify.sca.limit.file.size=100 -exclude "**/vendor/**" backend/
(這樣 Fortify 會自動跳過此類包含巨型模板的過大 PHP 檔)