| Index: src/wasm/module-decoder.cc | 
| diff --git a/src/wasm/module-decoder.cc b/src/wasm/module-decoder.cc | 
| index d3feb4c3571b62f673ad90ccefc26ea80b907680..c7d61896d6be35a2564c74e5adc303bda42f591e 100644 | 
| --- a/src/wasm/module-decoder.cc | 
| +++ b/src/wasm/module-decoder.cc | 
| @@ -609,22 +609,29 @@ class ModuleDecoder : public Decoder { | 
|  | 
| // ===== Name section ==================================================== | 
| if (section_iter.section_code() == kNameSectionCode) { | 
| -      uint32_t functions_count = consume_u32v("functions count"); | 
| +      // TODO(titzer): find a way to report name errors as warnings. | 
| +      // Use an inner decoder so that errors don't fail the outer decoder. | 
| +      Decoder inner(start_, pc_, end_); | 
| +      uint32_t functions_count = inner.consume_u32v("functions count"); | 
|  | 
| -      for (uint32_t i = 0; ok() && i < functions_count; ++i) { | 
| +      for (uint32_t i = 0; inner.ok() && i < functions_count; ++i) { | 
| uint32_t function_name_length = 0; | 
| -        uint32_t name_offset = consume_string(&function_name_length, false); | 
| +        uint32_t name_offset = | 
| +            consume_string(inner, &function_name_length, false); | 
| uint32_t func_index = i; | 
| if (func_index < module->functions.size()) { | 
| module->functions[func_index].name_offset = name_offset; | 
| module->functions[func_index].name_length = function_name_length; | 
| } | 
|  | 
| -        uint32_t local_names_count = consume_u32v("local names count"); | 
| +        uint32_t local_names_count = inner.consume_u32v("local names count"); | 
| for (uint32_t j = 0; ok() && j < local_names_count; j++) { | 
| -          skip_string(); | 
| +          uint32_t length = inner.consume_u32v("string length"); | 
| +          inner.consume_bytes(length, "string"); | 
| } | 
| } | 
| +      // Skip the whole names section in the outer decoder. | 
| +      consume_bytes(section_iter.payload_length(), nullptr); | 
| section_iter.advance(); | 
| } | 
|  | 
| @@ -810,27 +817,26 @@ class ModuleDecoder : public Decoder { | 
| } | 
| } | 
|  | 
| +  uint32_t consume_string(uint32_t* length, bool validate_utf8) { | 
| +    return consume_string(*this, length, validate_utf8); | 
| +  } | 
| + | 
| // Reads a length-prefixed string, checking that it is within bounds. Returns | 
| // the offset of the string, and the length as an out parameter. | 
| -  uint32_t consume_string(uint32_t* length, bool validate_utf8) { | 
| -    *length = consume_u32v("string length"); | 
| -    uint32_t offset = pc_offset(); | 
| -    const byte* string_start = pc_; | 
| +  uint32_t consume_string(Decoder& decoder, uint32_t* length, | 
| +                          bool validate_utf8) { | 
| +    *length = decoder.consume_u32v("string length"); | 
| +    uint32_t offset = decoder.pc_offset(); | 
| +    const byte* string_start = decoder.pc(); | 
| // Consume bytes before validation to guarantee that the string is not oob. | 
| -    if (*length > 0) consume_bytes(*length, "string"); | 
| -    if (ok() && validate_utf8 && | 
| +    if (*length > 0) decoder.consume_bytes(*length, "string"); | 
| +    if (decoder.ok() && validate_utf8 && | 
| !unibrow::Utf8::Validate(string_start, *length)) { | 
| -      error(string_start, "no valid UTF-8 string"); | 
| +      decoder.error(string_start, "no valid UTF-8 string"); | 
| } | 
| return offset; | 
| } | 
|  | 
| -  // Skips over a length-prefixed string, but checks that it is within bounds. | 
| -  void skip_string() { | 
| -    uint32_t length = consume_u32v("string length"); | 
| -    consume_bytes(length, "string"); | 
| -  } | 
| - | 
| uint32_t consume_sig_index(WasmModule* module, FunctionSig** sig) { | 
| const byte* pos = pc_; | 
| uint32_t sig_index = consume_u32v("signature index"); | 
|  |