Function: highlight-confusing-reorderings
highlight-confusing-reorderings is an interactive and byte-compiled
function defined in mule-cmds.el.gz.
Signature
(highlight-confusing-reorderings BEG END &optional REMOVE)
Documentation
Highlight text in region that might be bidi-reordered in suspicious ways.
This command find and highlights segments of buffer text that could have
been reordered on display by using directional control characters, such
as RLO and LRI, in a way that their display is deliberately meant to
confuse the reader. These techniques can be used for obfuscating
malicious source code. The suspicious stretches of buffer text are
highlighted using the confusingly-reordered face.
If the region is active, check the text inside the region. Otherwise check the entire buffer. When called from Lisp, pass BEG and END to specify the portion of the buffer to check.
Optional argument REMOVE, if non-nil (interactively, prefix argument), means remove the highlighting from the region between BEG and END, or the active region if that is set.
Probably introduced at or before Emacs version 29.1.
Key Bindings
Source Code
;; Defined in /usr/src/emacs/lisp/international/mule-cmds.el.gz
(defun highlight-confusing-reorderings (beg end &optional remove)
"Highlight text in region that might be bidi-reordered in suspicious ways.
This command find and highlights segments of buffer text that could have
been reordered on display by using directional control characters, such
as RLO and LRI, in a way that their display is deliberately meant to
confuse the reader. These techniques can be used for obfuscating
malicious source code. The suspicious stretches of buffer text are
highlighted using the `confusingly-reordered' face.
If the region is active, check the text inside the region. Otherwise
check the entire buffer. When called from Lisp, pass BEG and END to
specify the portion of the buffer to check.
Optional argument REMOVE, if non-nil (interactively, prefix argument),
means remove the highlighting from the region between BEG and END,
or the active region if that is set."
(interactive
(if (use-region-p)
(list (region-beginning) (region-end) current-prefix-arg)
(list (point-min) (point-max) current-prefix-arg)))
(save-excursion
(if remove
(let (prop-match)
(goto-char beg)
(while (and
(setq prop-match
(text-property-search-forward 'font-lock-face
'confusingly-reordered t))
(< (prop-match-beginning prop-match) end))
(with-silent-modifications
(remove-list-of-text-properties (prop-match-beginning prop-match)
(prop-match-end prop-match)
'(font-lock-face face mouse-face
help-echo)))))
(let ((count 0)
next)
(goto-char beg)
(while (setq next
(bidi-find-overridden-directionality
(point) end nil
(current-bidi-paragraph-direction)))
(goto-char next)
;; We detect the problematic parts by watching directional
;; properties of strong L2R and R2L characters. But
;; malicious reordering in source buffers can, and usuually
;; does, include syntactically-important punctuation
;; characters. Those have "weak" directionality, so we
;; cannot easily detect when they are affected in malicious
;; ways. Therefore, once we find a strong directional
;; character whose directionality was tweaked, we highlight
;; the text around it, between the first bidi control
;; character we find before it that starts an
;; override/embedding/isolate, and the first control after
;; it that ends these. This could sometimes highlight only
;; part of the affected text. An alternative would be to
;; find the first "starter" following BOL and the last
;; "ender" before EOL, and highlight everything in between
;; them -- this could sometimes highlight too much.
(let ((start
(save-excursion
(re-search-backward reorder-starters nil t)))
(finish
(save-excursion
(let ((fin (re-search-forward reorder-enders nil t)))
(if fin (1- fin)
(point-max))))))
(with-silent-modifications
(add-text-properties start finish
'(font-lock-face
confusingly-reordered
face confusingly-reordered
mouse-face highlight
help-echo "\
This text is reordered on display in a way that could change its semantics;
use \\[forward-char] and \\[backward-char] to see the actual order of characters.")))
(goto-char finish)
(setq count (1+ count))))
(message
(if (> count 0)
(ngettext
"Highlighted %d confusingly-reordered text string"
"Highlighted %d confusingly-reordered text strings"
count)
"No confusingly-reordered text strings were found")
count)))))