Uploaded image for project: 'Sakai'
  1. Sakai
  2. SAK-37102

ArrayIndexOutOfBoundsException protection in HistogramListener.doAnswerStatistics()

    XMLWordPrintable

    Details

    • 12 status:
      Resolved
    • Previous Issue Keys:
      SAM-3392
    • Test Plan:
      Hide

      Please add a Test Plan here.

      Show
      Please add a Test Plan here.

      Description

      We ran into an issue recently in our production environment where a user was not able to access the Statistics or Export pages of a published quiz. The failure was caused by an uncaught IndexOutOfBoundsException in HistogramListener.doAnswerStatistics():

      org.sakaiproject.portal.api.PortalHandlerException: org.sakaiproject.tool.api.ToolException: javax.servlet.ServletException: 0
          at org.sakaiproject.portal.charon.handlers.ToolHandler.doPost(ToolHandler.java:77)
      caused by: org.sakaiproject.tool.api.ToolException: javax.servlet.ServletException: 0
          at org.sakaiproject.portal.charon.SkinnableCharonPortal.forwardTool(SkinnableCharonPortal.java:1492)
      caused by: javax.servlet.ServletException: 0
          at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
      caused by: java.lang.ArrayIndexOutOfBoundsException: 0
          at org.sakaiproject.tool.assessment.ui.listener.evaluation.HistogramListener.doAnswerStatistics(HistogramListener.java:902)
          at org.sakaiproject.tool.assessment.ui.listener.evaluation.HistogramListener.determineResults(HistogramListener.java:818)
          at org.sakaiproject.tool.assessment.ui.listener.evaluation.HistogramListener.histogramScores(HistogramListener.java:461)
          at org.sakaiproject.tool.assessment.ui.listener.evaluation.HistogramListener.processAction(HistogramListener.java:113)
          at javax.faces.event.ActionEvent.processListener(ActionEvent.java:88)
          at javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:774)
          at javax.faces.component.UICommand.broadcast(UICommand.java:372)
          at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:475)
          at javax.faces.component.UIViewRoot.processDecodes(UIViewRoot.java:541)
          at com.sun.faces.lifecycle.ApplyRequestValuesPhase.execute(ApplyRequestValuesPhase.java:78)
          at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100)
          at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
          at javax.faces.webapp.FacesServlet.service(FacesServlet.java:265)
          at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
          at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
          at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
          at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
          at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
          at org.sakaiproject.util.RequestFilter.doFilter(RequestFilter.java:411)
          at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
          at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
          at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:716)
          at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:466)
          at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:391)
          at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:318)
          at org.sakaiproject.jsf.util.SamigoJsfTool.dispatch(SamigoJsfTool.java:318)
          at org.sakaiproject.jsf.util.JsfTool.doPost(JsfTool.java:260)
          at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
          at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
          at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
          at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
          at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:716)
          at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:466)
          at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:358)
          at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:318)
          at org.sakaiproject.tool.impl.ActiveToolComponent$MyActiveTool.forward(ActiveToolComponent.java:513)
          at org.sakaiproject.portal.charon.SkinnableCharonPortal.forwardTool(SkinnableCharonPortal.java:1492)
          at org.sakaiproject.portal.charon.handlers.ToolHandler.doTool(ToolHandler.java:204)
          at org.sakaiproject.portal.charon.handlers.ToolHandler.doGet(ToolHandler.java:100)
          at org.sakaiproject.portal.charon.handlers.ToolHandler.doPost(ToolHandler.java:77)
          at org.sakaiproject.portal.charon.SkinnableCharonPortal.doPost(SkinnableCharonPortal.java:1167)
          at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
          at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
          at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
          at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
          at org.sakaiproject.util.RequestFilter.doFilter(RequestFilter.java:460)
          at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
          at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
          at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
          at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
          at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
          at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
          at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:94)
          at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:504)
          at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
          at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
          at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:620)
          at org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:676)
          at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
          at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:502)
          at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1132)
          at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:684)
          at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1533)
          at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1489)
          at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
          at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
          at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
          at java.lang.Thread.run(Thread.java:745)
      

      After investigation, we found that the cause of this was a specific question in a question pool the quiz was drawing from. The offending question had no type, no question text, and had no answers (or really any information at all); it was a 'shell' of a question.

      We were unable to reproduce any situation that would allow us to create such an erroneous question. So we're not sure how the question came into existence, but putting in a simple size check allows the code to complete without exploding.

        Gliffy Diagrams

          Attachments

            Activity

              People

              • Assignee:
                bjones86 Brian Jones
                Reporter:
                bjones86 Brian Jones
              • Votes:
                0 Vote for this issue
                Watchers:
                2 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved:

                  Git Source Code