From 9534188f1f27eda25506371a86be0e98ad8d4d82 Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Tue, 21 Oct 2025 17:16:39 -0400 Subject: [PATCH] Add react precallgraphstep useRef --- .../2025-10-21-react-precallgraph-step.md | 4 ++++ .../semmle/javascript/frameworks/React.qll | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 javascript/ql/lib/change-notes/2025-10-21-react-precallgraph-step.md diff --git a/javascript/ql/lib/change-notes/2025-10-21-react-precallgraph-step.md b/javascript/ql/lib/change-notes/2025-10-21-react-precallgraph-step.md new file mode 100644 index 00000000000..efba56b3470 --- /dev/null +++ b/javascript/ql/lib/change-notes/2025-10-21-react-precallgraph-step.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Added PreCallGraphStep flow model for React's `useRef` hook. \ No newline at end of file diff --git a/javascript/ql/lib/semmle/javascript/frameworks/React.qll b/javascript/ql/lib/semmle/javascript/frameworks/React.qll index d55ace8636d..946b09ffd44 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/React.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/React.qll @@ -612,6 +612,25 @@ private class UseStateStep extends PreCallGraphStep { } } +/** + * Step through a `useRef` call. + * + * It returns a pair of the initial state, and an object with a single property (current) potentially containing an input value. + * + * For example: + * ```js + * const inputRef1 = useRef(initialValue); + * ``` + */ +private class UseRefStep extends PreCallGraphStep { + override predicate step(DataFlow::Node pred, DataFlow::Node succ) { + exists(DataFlow::CallNode call | call = react().getAMemberCall("useRef") | + pred = call.getArgument(0) and // initial state + succ = call.getAPropertyRead("current") + ) + } +} + /** * A step through a React context object. *