Class: RemLint::Rules::UnquotedShellSubstitution

Inherits:
RemLint::Rule show all
Defined in:
lib/remlint/rules/unquoted_shell_substitution.rb

Overview

Reminder text pasted into a shell command without quotes.

RUN and INCLUDECMD bodies go through Remind's substitution filter and the result is handed to /bin/sh. So %s, %<Location> and [expr] are not text in a shell command -- they are holes in one, and what lands in them is data: a reminder body, a place name, somebody's surname.

REM 1 Jan RUN notify-send [msg]        # msg = "Bob's party" -> broken
REM 1 Jan RUN notify-send "[msg]"      # quoted, and fine

An apostrophe is the polite failure. $(...), a backtick or a ; in the same position is a command running that nobody wrote, from a calendar, under cron, with the user's own privileges. Chapter 17's own INCLUDECMD example is careful to write L="[lessons]"; nothing enforces that care.

This reports only what it is sure of: a substitution sitting outside any quote. Quoting is tracked by walking the body character by character -- single quotes, double quotes, and the backslash escape inside double quotes -- because that is what the shell does with it.

A body with no substitution at all is not this rule's business: a fixed RUN echo hello has no hole for anything to land in.

Constant Summary collapse

SUBSTITUTION =

Every hole the author did not write the contents of: the % sequences in all their forms, and a pasted [expr].

/%\*?(?<simple><[^>]*>|\{[^}]*\}|\([^)]*\)|.)|\[[^\]]*\]/
CONSTANT =

Sequences that expand to something fixed rather than to reminder data, and so are not holes:

%"  the calendar-text marker, which NORMAL_MODE deletes outright
%%  a literal percent
%_  a newline or a space

Remind's own tests/dedupe.rem writes RUN echo %"foo%"; there is no data in that command for anyone to inject through.

%w[" % _].freeze

Constants inherited from RemLint::Rule

RemLint::Rule::REGISTRY

Instance Attribute Summary

Attributes inherited from RemLint::Rule

#config, #document, #offenses

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from RemLint::Rule

all, enabled_by_default?, find, inherited, #initialize, rule_name, #rule_name, #run

Constructor Details

This class inherits a constructor from RemLint::Rule

Class Method Details

.default_severityObject



45
46
47
# File 'lib/remlint/rules/unquoted_shell_substitution.rb', line 45

def self.default_severity
  "error"
end

.descriptionObject



49
50
51
# File 'lib/remlint/rules/unquoted_shell_substitution.rb', line 49

def self.description
  "Reminder text pasted into a RUN or INCLUDECMD body outside shell quotes."
end

Instance Method Details

#checkObject



53
54
55
56
57
58
59
60
61
# File 'lib/remlint/rules/unquoted_shell_substitution.rb', line 53

def check
  document.code_commands.each do |command|
    body = shell_body(command)

    if body
      report_unquoted(command, body.fetch(:text), body.fetch(:offset))
    end
  end
end