Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-37446

StringIndexOutOfBoundsException when editing Custom Configuration field

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: Minor Minor
    • mercurial-plugin
    • Windows 7 x64
      Jenkins 1.580.3
      Mercurial plugin 1.54

      In the Jenkins configuration page, under Mercurial installations, I get an exception if I enter this specific text in the Custom Configuration field:

      [x]
      \:
      

      There can be any text around these elements, but this appears to be the minimal amount of text that produces the exception.

      The exception pops as a web page under the field, with Jenkins top header and sidebar, which is kinda weird, too (see attached image).

      Here's the full text of the exception that is displayed:

      javax.servlet.ServletException: java.lang.StringIndexOutOfBoundsException: String index out of range: 1
      	at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:795)
      	at org.kohsuke.stapler.Stapler.invoke(Stapler.java:875)
      	at org.kohsuke.stapler.MetaClass$6.doDispatch(MetaClass.java:249)
      	at org.kohsuke.stapler.NameBasedDispatcher.dispatch(NameBasedDispatcher.java:53)
      	at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:745)
      	at org.kohsuke.stapler.Stapler.invoke(Stapler.java:875)
      	at org.kohsuke.stapler.Stapler.invoke(Stapler.java:648)
      	at org.kohsuke.stapler.Stapler.service(Stapler.java:237)
      	at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
      	at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:686)
      	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1494)
      	at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:96)
      	at hudson.util.PluginServletFilter.doFilter(PluginServletFilter.java:88)
      	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1482)
      	at hudson.security.csrf.CrumbFilter.doFilter(CrumbFilter.java:48)
      	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1482)
      	at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:84)
      	at hudson.security.UnwrapSecurityExceptionFilter.doFilter(UnwrapSecurityExceptionFilter.java:51)
      	at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
      	at jenkins.security.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:117)
      	at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
      	at org.acegisecurity.providers.anonymous.AnonymousProcessingFilter.doFilter(AnonymousProcessingFilter.java:125)
      	at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
      	at org.acegisecurity.ui.rememberme.RememberMeProcessingFilter.doFilter(RememberMeProcessingFilter.java:142)
      	at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
      	at org.acegisecurity.ui.AbstractProcessingFilter.doFilter(AbstractProcessingFilter.java:271)
      	at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
      	at jenkins.security.BasicHeaderProcessor.doFilter(BasicHeaderProcessor.java:93)
      	at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
      	at org.acegisecurity.context.HttpSessionContextIntegrationFilter.doFilter(HttpSessionContextIntegrationFilter.java:249)
      	at hudson.security.HttpSessionContextIntegrationFilter2.doFilter(HttpSessionContextIntegrationFilter2.java:67)
      	at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
      	at hudson.security.ChainedServletFilter.doFilter(ChainedServletFilter.java:76)
      	at hudson.security.HudsonFilter.doFilter(HudsonFilter.java:164)
      	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1482)
      	at org.kohsuke.stapler.compression.CompressionFilter.doFilter(CompressionFilter.java:46)
      	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1482)
      	at hudson.util.CharacterEncodingFilter.doFilter(CharacterEncodingFilter.java:81)
      	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1474)
      	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:499)
      	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:137)
      	at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:533)
      	at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231)
      	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1086)
      	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:428)
      	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193)
      	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1020)
      	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
      	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
      	at org.eclipse.jetty.server.Server.handle(Server.java:370)
      	at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:489)
      	at org.eclipse.jetty.server.AbstractHttpConnection.headerComplete(AbstractHttpConnection.java:949)
      	at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:1011)
      	at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:644)
      	at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:235)
      	at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82)
      	at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:668)
      	at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:52)
      	at winstone.BoundedExecutorService$1.run(BoundedExecutorService.java:77)
      	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
      	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
      	at java.lang.Thread.run(Unknown Source)
      Caused by: java.lang.StringIndexOutOfBoundsException: String index out of range: 1
      	at java.lang.String.charAt(Unknown Source)
      	at org.ini4j.spi.EscapeTool.unescape(EscapeTool.java:111)
      	at org.ini4j.spi.AbstractParser.unescapeFilter(AbstractParser.java:109)
      	at org.ini4j.spi.AbstractParser.parseOptionLine(AbstractParser.java:90)
      	at org.ini4j.spi.IniParser.parse(IniParser.java:101)
      	at org.ini4j.spi.IniParser.parse(IniParser.java:62)
      	at org.ini4j.Ini.load(Ini.java:109)
      	at org.ini4j.Ini.<init>(Ini.java:50)
      	at hudson.plugins.mercurial.MercurialInstallation$DescriptorImpl.doCheckConfig(MercurialInstallation.java:161)
      	at sun.reflect.GeneratedMethodAccessor1055.invoke(Unknown Source)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
      	at java.lang.reflect.Method.invoke(Unknown Source)
      	at org.kohsuke.stapler.Function$InstanceFunction.invoke(Function.java:298)
      	at org.kohsuke.stapler.Function.bindAndInvoke(Function.java:161)
      	at org.kohsuke.stapler.Function.bindAndInvokeAndServeResponse(Function.java:96)
      	at org.kohsuke.stapler.MetaClass$1.doDispatch(MetaClass.java:121)
      	at org.kohsuke.stapler.NameBasedDispatcher.dispatch(NameBasedDispatcher.java:53)
      	at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:745)
      	... 61 more
      

      I'm not sure if that exception even has an effect on anything, and I have an easy workaround, which is to use [:] instead of \: in my regex.

      The config I was trying to use was this, if you're wondering why I even had that kind of pattern in there:

      [subpaths]
      (http|https|ssh)(\://.*)/src/(.*) = \1\2-subrepos/\3
      

          [JENKINS-37446] StringIndexOutOfBoundsException when editing Custom Configuration field

          It seems my workaround is not working either...

          Using this config:

          [subpaths]
          (http|https|ssh)([:]//.*)/src/(.*) = \1\2-subrepos/\3
          

          results in this when I run my job:

          [MyJob] $ hg --config "subpaths.(http|https|ssh)([=]//.*)/src/(.*) = 12-subrepos/3" --config auth.jenkins.prefix=* --config ******** --config ******** --config "auth.jenkins.schemes=http https" showconfig paths.default
          

          The ":" was transformed to a "=" somehow... I also noticed my backslashes got removed, so I had to escape them in the configuration field.

          Samuel Delisle added a comment - It seems my workaround is not working either... Using this config: [subpaths] (http|https|ssh)([:]//.*)/src/(.*) = \1\2-subrepos/\3 results in this when I run my job: [MyJob] $ hg --config "subpaths.(http|https|ssh)([=]//.*)/src/(.*) = 12-subrepos/3" --config auth.jenkins.prefix=* --config ******** --config ******** --config "auth.jenkins.schemes=http https" showconfig paths.default The ":" was transformed to a "=" somehow... I also noticed my backslashes got removed, so I had to escape them in the configuration field.

          I hit the same bug trying to specify hostname:minimumprotocol = tls1.x . It prevents me from using the plugin with our old company Mercurial server

          Michael Piffret added a comment - I hit the same bug trying to specify hostname:minimumprotocol = tls1.x . It prevents me from using the plugin with our old company Mercurial server

          I tracked it down to Ini4j : its IniParser defines "private static final" operators, ':' and '='. I does not manage escape characters properly, it does not seem to provide a way to override these operators.

          When given "option:suboption = value" it understands "option = 'suboption = value'". I suppose it was never able to handle Mercurial configuration files... I'm thinking about some kind of solution, any input is welcome !

          Michael Piffret added a comment - I tracked it down to Ini4j : its IniParser defines "private static final" operators, ':' and '='. I does not manage escape characters properly, it does not seem to provide a way to override these operators. When given "option:suboption = value" it understands "option = 'suboption = value'". I suppose it was never able to handle Mercurial configuration files... I'm thinking about some kind of solution, any input is welcome !

          If the parsing of the ini file is modified for this, it might also be possible to fix JENKINS-38038 at the same time so that the order of the confg lines is also preserved.

          Samuel Delisle added a comment - If the parsing of the ini file is modified for this, it might also be possible to fix JENKINS-38038 at the same time so that the order of the confg lines is also preserved.

          This would be great.

          We could suggest a few modifications to the ini4j library, hopefully they'll take pull request (or patches or whatever) though releases seem to be few and far between.

          Michael Piffret added a comment - This would be great. We could suggest a few modifications to the ini4j library, hopefully they'll take pull request (or patches or whatever) though releases seem to be few and far between.

          Jesse Glick added a comment -

          Offhand it does sound like a patched version of ini4j is likely to be needed.

          As a workaround, just define a wrapper script like

          hg --config whatever --other-options-you-need "$@"
          

          and set that as the executable.

          Jesse Glick added a comment - Offhand it does sound like a patched version of ini4j is likely to be needed. As a workaround, just define a wrapper script like hg --config whatever --other-options-you-need "$@" and set that as the executable.

          For the record, there's an issue filed for this, on the ini4j SourceForge project page, since 2012 : https://sourceforge.net/p/ini4j/bugs/45/

          I'm not sure how I'd be supposed to work with CVS and SourceForge to provide some patch though ! Feels otherworldly to me.

          Michael Piffret added a comment - For the record, there's an issue filed for this, on the ini4j SourceForge project page, since 2012 : https://sourceforge.net/p/ini4j/bugs/45/ I'm not sure how I'd be supposed to work with CVS and SourceForge to provide some patch though ! Feels otherworldly to me.

          Jesse Glick added a comment -

          I guess you have to attach a *.diff file. Does feel like the previous millenium.

          Jesse Glick added a comment - I guess you have to attach a *.diff file. Does feel like the previous millenium.

            jglick Jesse Glick
            samapico Samuel Delisle
            Votes:
            1 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: