Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
macaron.code\_analyzer.dataflow\_analysis package
=================================================

.. automodule:: macaron.code_analyzer.dataflow_analysis
:members:
:show-inheritance:
:undoc-members:

Submodules
----------

macaron.code\_analyzer.dataflow\_analysis.analysis module
---------------------------------------------------------

.. automodule:: macaron.code_analyzer.dataflow_analysis.analysis
:members:
:show-inheritance:
:undoc-members:

macaron.code\_analyzer.dataflow\_analysis.bash module
-----------------------------------------------------

.. automodule:: macaron.code_analyzer.dataflow_analysis.bash
:members:
:show-inheritance:
:undoc-members:

macaron.code\_analyzer.dataflow\_analysis.cmd\_parser module
------------------------------------------------------------

.. automodule:: macaron.code_analyzer.dataflow_analysis.cmd_parser
:members:
:show-inheritance:
:undoc-members:

macaron.code\_analyzer.dataflow\_analysis.core module
-----------------------------------------------------

.. automodule:: macaron.code_analyzer.dataflow_analysis.core
:members:
:show-inheritance:
:undoc-members:

macaron.code\_analyzer.dataflow\_analysis.evaluation module
-----------------------------------------------------------

.. automodule:: macaron.code_analyzer.dataflow_analysis.evaluation
:members:
:show-inheritance:
:undoc-members:

macaron.code\_analyzer.dataflow\_analysis.facts module
------------------------------------------------------

.. automodule:: macaron.code_analyzer.dataflow_analysis.facts
:members:
:show-inheritance:
:undoc-members:

macaron.code\_analyzer.dataflow\_analysis.github module
-------------------------------------------------------

.. automodule:: macaron.code_analyzer.dataflow_analysis.github
:members:
:show-inheritance:
:undoc-members:

macaron.code\_analyzer.dataflow\_analysis.github\_expr module
-------------------------------------------------------------

.. automodule:: macaron.code_analyzer.dataflow_analysis.github_expr
:members:
:show-inheritance:
:undoc-members:

macaron.code\_analyzer.dataflow\_analysis.models module
-------------------------------------------------------

.. automodule:: macaron.code_analyzer.dataflow_analysis.models
:members:
:show-inheritance:
:undoc-members:

macaron.code\_analyzer.dataflow\_analysis.printing module
---------------------------------------------------------

.. automodule:: macaron.code_analyzer.dataflow_analysis.printing
:members:
:show-inheritance:
:undoc-members:

macaron.code\_analyzer.dataflow\_analysis.run\_analysis\_standalone module
--------------------------------------------------------------------------

.. automodule:: macaron.code_analyzer.dataflow_analysis.run_analysis_standalone
:members:
:show-inheritance:
:undoc-members:
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,10 @@ macaron.code\_analyzer package
:show-inheritance:
:undoc-members:

Submodules
----------
Subpackages
-----------

macaron.code\_analyzer.call\_graph module
-----------------------------------------
.. toctree::
:maxdepth: 1

.. automodule:: macaron.code_analyzer.call_graph
:members:
:show-inheritance:
:undoc-members:
macaron.code_analyzer.dataflow_analysis
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ macaron.parsers.bashparser module
:show-inheritance:
:undoc-members:

macaron.parsers.bashparser\_model module
----------------------------------------

.. automodule:: macaron.parsers.bashparser_model
:members:
:show-inheritance:
:undoc-members:

macaron.parsers.github\_workflow\_model module
----------------------------------------------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,6 @@ macaron.slsa\_analyzer.ci\_service.github\_actions package
Submodules
----------

macaron.slsa\_analyzer.ci\_service.github\_actions.analyzer module
------------------------------------------------------------------

.. automodule:: macaron.slsa_analyzer.ci_service.github_actions.analyzer
:members:
:show-inheritance:
:undoc-members:

macaron.slsa\_analyzer.ci\_service.github\_actions.github\_actions\_ci module
-----------------------------------------------------------------------------

Expand Down
59 changes: 59 additions & 0 deletions golang/cmd/bashexprparser/bashexprparser.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/* Copyright (c) 2025 - 2025, Oracle and/or its affiliates. All rights reserved. */
/* Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/. */

package main

import (
"flag"
"fmt"
"os"

"github.com/oracle/macaron/golang/internal/bashparser"
"github.com/oracle/macaron/golang/internal/filewriter"
)

// Parse the bash expression and provide parsed objects in JSON format to stdout or a file.
// Params:
//
// -input <EXPR_CONTENT>: the bash expr content in string
// -output <OUTPUT_FILE>: the output file path to store the JSON content
//
// Return code:
//
// 0 - Parse successfully, return the JSON as string to stdout. If -output is set, store the json content to the file.
// If there is any errors storing to file, the result is still printed to stdout, but the errors are put to stderr instead.
// 1 - Error: Missing bash script or output file paths.
// 2 - Error: Could not parse the bash script file. Parse errors will be printed to stderr.
func main() {
input := flag.String("input", "", "The bash expr content to be parsed.")
out_path := flag.String("output", "", "The output file path to store the JSON content.")
flag.Parse()

var json_content string
var parse_err error
if len(*input) <= 0 {
fmt.Fprintln(os.Stderr, "Missing bash expr input.")
flag.PrintDefaults()
os.Exit(1)
} else {
// Read the bash script from command line argument.
json_content, parse_err = bashparser.ParseExpr(*input)
}

if parse_err != nil {
fmt.Fprintln(os.Stderr, parse_err.Error())
os.Exit(2)
}

fmt.Println(json_content)

if len(*out_path) > 0 {
err := filewriter.StoreBytesToFile([]byte(json_content), *out_path)
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1)
}
}

os.Exit(0)
}
7 changes: 4 additions & 3 deletions golang/cmd/bashparser/bashparser.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (c) 2022 - 2023, Oracle and/or its affiliates. All rights reserved. */
/* Copyright (c) 2022 - 2025, Oracle and/or its affiliates. All rights reserved. */
/* Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/. */

package main
Expand Down Expand Up @@ -29,13 +29,14 @@ func main() {
file_path := flag.String("file", "", "The path of the bash script file.")
input := flag.String("input", "", "The bash script content to be parsed. Input is prioritized over file option.")
out_path := flag.String("output", "", "The output file path to store the JSON content.")
raw := flag.Bool("raw", false, "Return raw parse-tree")
flag.Parse()

var json_content string
var parse_err error
if len(*input) > 0 {
// Read the bash script from command line argument.
json_content, parse_err = bashparser.ParseCommands(*input)
json_content, parse_err = bashparser.Parse(*input, *raw)
} else if len(*file_path) <= 0 {
fmt.Fprintln(os.Stderr, "Missing bash script input or file path.")
flag.PrintDefaults()
Expand All @@ -47,7 +48,7 @@ func main() {
fmt.Fprintln(os.Stderr, read_err.Error())
os.Exit(1)
}
json_content, parse_err = bashparser.ParseCommands(string(data))
json_content, parse_err = bashparser.Parse(string(data), *raw)
}

if parse_err != nil {
Expand Down
63 changes: 62 additions & 1 deletion golang/internal/bashparser/bashparser.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (c) 2022 - 2024, Oracle and/or its affiliates. All rights reserved. */
/* Copyright (c) 2022 - 2025, Oracle and/or its affiliates. All rights reserved. */
/* Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/. */

// Package bashparser parses the bash scripts and provides parsed objects in JSON.
Expand All @@ -11,6 +11,7 @@ import (
"strings"

"mvdan.cc/sh/v3/syntax"
"mvdan.cc/sh/v3/syntax/typedjson"
)

// CMDResult is used to export the bash command results in JSON.
Expand Down Expand Up @@ -68,3 +69,63 @@ func ParseCommands(data string) (string, error) {
return string(result_bytes), nil

}

func ParseRaw(data string) (string, error) {
// Replace GitHub Actions's expressions with ``$MACARON_UNKNOWN``` variable because the bash parser
// doesn't recognize such expressions. For example: ``${{ foo }}`` will be replaced by ``$MACARON_UNKNOWN``.
// Note that we don't use greedy matching, so if we have `${{ ${{ foo }} }}`, it will not be replaced by
// `$MACARON_UNKNOWN`.
// See: https://docs.github.com/en/actions/learn-github-actions/expressions.
var re, reg_error = regexp.Compile(`\$\{\{.*?\}\}`)
if reg_error != nil {
return "", reg_error
}

// We replace the GH Actions variables with "$MACARON_UNKNOWN".
data = string(re.ReplaceAll([]byte(data), []byte("$$MACARON_UNKNOWN")))
data_str := strings.NewReader(data)
data_parsed, parse_err := syntax.NewParser().Parse(data_str, "")
if parse_err != nil {
return "", parse_err
}

b := new(strings.Builder)
encode_err := typedjson.Encode(b, data_parsed)
if encode_err != nil {
return "", encode_err
}

return b.String(), nil
}

func Parse(data string, raw bool) (string, error) {
if raw {
return ParseRaw(data)
} else {
return ParseCommands(data)
}
}

func ParseExpr(data string) (string, error) {
data_str := strings.NewReader(data)
result_str := "["
first := true
for word_parsed, parse_err := range syntax.NewParser().WordsSeq(data_str) {
if parse_err != nil {
return "", parse_err
}
b := new(strings.Builder)
encode_err := typedjson.Encode(b, word_parsed)
if encode_err != nil {
return "", encode_err
}
if first {
result_str = result_str + b.String()
first = false
} else {
result_str = result_str + ", " + b.String()
}
}
result_str = result_str + "]"
return result_str, nil
}
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ dependencies = [
"semgrep == 1.113.0",
"email-validator >=2.2.0,<3.0.0",
"rich >=13.5.3,<15.0.0",
"lark >= 1.3.0,<2.0.0",
"frozendict >= 2.4.6, <3.0.0",
]
keywords = []
# https://pypi.org/classifiers/
Expand Down
Loading
Loading