[PUP-7475] A regex literal for matching backslashes causes a lexer error Created: 2017/04/26  Updated: 2017/06/14  Resolved: 2017/05/15

Status: Closed
Project: Puppet
Component/s: Language
Affects Version/s: PUP 4.10.0
Fix Version/s: PUP 4.10.2, PUP 5.0.0

Type: Bug Priority: Normal
Reporter: Charlie Sharpsteen Assignee: Unassigned
Resolution: Fixed Votes: 0
Labels: resolved-issue-added
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Template:
Team: Puppet Developer Experience
Story Points: 1
Sprint: PDE 2017-05-03, PDE 2017-05-31
Release Notes: Bug Fix
Release Notes Summary: A literal regex for matching a backslash would cause a lexer error. This is now fixed.
QA Risk Assessment: No Action
QA Risk Assessment Reason: covered by unit tests

 Description   

Attempting to declare a regex literal for matching a single backslash results in a lexer error when the manifest is parsed.

Reproduction Case

Apply the following manifest which multiplies backslashes within a windows path:

$win_path = "c:\\some\\path"
$backslash = /\\/
 
$escaped_path = regsubst($win_path, $backslash, '\\\\\\\\', 'G')
 
 
notice("Escaped path is: ${escaped_path}")

Outcome

Applying the manifest results in a parser error coming from the lexer code.

# puppet apply regex_test.pp --trace
Error: Could not parse for environment production: no implicit conversion of nil into String on node pe-201643-master.puppetdebug.vlan
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/parser/lexer2.rb:380:in `+'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/parser/lexer2.rb:380:in `block in initialize'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/parser/lexer2.rb:710:in `call'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/parser/lexer2.rb:710:in `scan'
/opt/puppetlabs/puppet/lib/ruby/2.1.0/racc/parser.rb:319:in `_racc_yyparse_c'
/opt/puppetlabs/puppet/lib/ruby/2.1.0/racc/parser.rb:319:in `yyparse'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/parser/parser_support.rb:240:in `_parse'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/parser/parser_support.rb:84:in `parse_file'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/parser/evaluating_parser.rb:41:in `parse_file'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/parser/e4_parser_adapter.rb:31:in `parse'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/node/environment.rb:512:in `perform_initial_import'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/node/environment.rb:236:in `known_resource_types'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/parser/compiler.rb:762:in `block in initvars'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/context.rb:65:in `override'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet.rb:241:in `override'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/parser/compiler.rb:760:in `initvars'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/parser/compiler.rb:422:in `initialize'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/parser/compiler.rb:33:in `new'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/parser/compiler.rb:33:in `compile'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/indirector/catalog/compiler.rb:266:in `block (2 levels) in compile'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/util/profiler/around_profiler.rb:58:in `profile'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/util/profiler.rb:51:in `profile'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/indirector/catalog/compiler.rb:264:in `block in compile'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/util.rb:223:in `block in benchmark'
/opt/puppetlabs/puppet/lib/ruby/2.1.0/benchmark.rb:294:in `realtime'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/util.rb:222:in `benchmark'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/indirector/catalog/compiler.rb:262:in `compile'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/indirector/catalog/compiler.rb:53:in `find'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/indirector/indirection.rb:194:in `find'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/application/apply.rb:256:in `block in main'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/context.rb:65:in `override'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet.rb:241:in `override'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/application/apply.rb:225:in `main'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/application/apply.rb:170:in `run_command'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/application.rb:344:in `block in run'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/util.rb:540:in `exit_on_fail'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/application.rb:344:in `run'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/util/command_line.rb:132:in `run'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/util/command_line.rb:72:in `execute'
/opt/puppetlabs/puppet/bin/puppet:5:in `<main>'

Expected Outcome

Notice: Scope(Class[main]): Escaped path is: c:\\some\\path

Recommended Workaround

Enclosing the backslashes in a capture group allows a regex literal to be constructed:

$backslash = /(\\)/



 Comments   
Comment by John Duarte [ 2017/05/15 ]

This passed CI as a component of puppet-agent at SHA 9de43c457ea423af31c6d9f0cc60316b523ef9ad

Generated at Sat Aug 24 21:37:38 PDT 2019 using JIRA 7.7.1#77002-sha1:e75ca93d5574d9409c0630b81c894d9065296414.