CVE-2020-13649 (C, published 2020-05-28T15:15Z)
Description: value: parser/js/js-scanner.c in JerryScript 2.2.0 mishandles errors during certain out-of-memory conditions, as demonstrated by a scanner_reverse_info_list NULL pointer dereference and a scanner_scan_all assertion failure.
Severity: MEDIUM (CVSS v3 base score: 7.5)
Weakness: CWE-754 \u2014 Improper Check for Unusual or Exceptional Conditions
The product does not check or incorrectly checks for unusual or exceptional conditions that are not expected to occur frequently during day to day operation of the product.
Repository: https://github.com/jerryscript-project/jerryscript
Files changed:
jerry-core/parser/js/js-scanner.c
Commit message: Fix error handling in scanner when in case of OOM (#3793)

This patch fixes #3786 and fixes #3788.

JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu

Vulnerable code:
    /* Ignore the errors thrown by the lexer. */
    if (context_p->error != PARSER_ERR_OUT_OF_MEMORY)
    {
      context_p->error = PARSER_ERR_NO_ERROR;
    }

    /* The following code may allocate memory, so it is enclosed in a try/catch. */
    PARSER_TRY (context_p->try_buffer)
#if ENABLED (JERRY_ES2015)
      if (scanner_context.status_flags & SCANNER_CONTEXT_THROW_ERR_ASYNC_FUNCTION)
        JERRY_ASSERT (scanner_context.async_source_p != NULL);
        scanner_info_t *info_p;
        info_p = scanner_insert_info (context_p, scanner_context.async_source_p, sizeof (scanner_info_t));
        info_p->type = SCANNER_TYPE_ERR_ASYNC_FUNCTION;
      }
#endif /* ENABLED (JERRY_ES2015) */
      while (scanner_context.active_literal_pool_p != NULL)
        scanner_pop_literal_pool (context_p, &scanner_context);
    PARSER_CATCH
    {
      JERRY_ASSERT (context_p->error == PARSER_ERR_NO_ERROR);
    }
    PARSER_TRY_END
#if ENABLED (JERRY_ES2015)
    context_p->status_flags &= (uint32_t) ~PARSER_IS_GENERATOR_FUNCTION;
#endif /* ENABLED (JERRY_ES2015) */

Fixed code:
    if (JERRY_UNLIKELY (context_p->error != PARSER_ERR_OUT_OF_MEMORY))
      /* Ignore the errors thrown by the lexer. */
      context_p->error = PARSER_ERR_NO_ERROR;

      /* The following code may allocate memory, so it is enclosed in a try/catch. */
      PARSER_TRY (context_p->try_buffer)
  #if ENABLED (JERRY_ES2015)
        if (scanner_context.status_flags & SCANNER_CONTEXT_THROW_ERR_ASYNC_FUNCTION)
        {
          JERRY_ASSERT (scanner_context.async_source_p != NULL);
          scanner_info_t *info_p;
          info_p = scanner_insert_info (context_p, scanner_context.async_source_p, sizeof (scanner_info_t));
          info_p->type = SCANNER_TYPE_ERR_ASYNC_FUNCTION;
        }
  #endif /* ENABLED (JERRY_ES2015) */
        while (scanner_context.active_literal_pool_p != NULL)
        {
          scanner_pop_literal_pool (context_p, &scanner_context);
        }
      }
      PARSER_CATCH
        JERRY_ASSERT (context_p->error == PARSER_ERR_OUT_OF_MEMORY);
      PARSER_TRY_END
    JERRY_ASSERT (context_p->error == PARSER_ERR_NO_ERROR || context_p->error == PARSER_ERR_OUT_OF_MEMORY);

    if (context_p->error == PARSER_ERR_OUT_OF_MEMORY)
    {
      parser_stack_free (context_p);
      return;
    }