From f6fdae755f77250cc3a68a76c969229ffb81b158 Mon Sep 17 00:00:00 2001
From: Esun Kim <veblush@google.com>
Date: Tue, 19 Nov 2019 09:51:20 -0800
Subject: [PATCH] Squashed 'third_party/upb/' changes from
 9effcbcb27..8a3ae1ef3e

8a3ae1ef3e Merge pull request #229 from veblush/zlib
34e55c1c56 Use github.com as a zlib repo
f32f2fdb25 Merge pull request #221 from haberman/endsubmsg
ea99941f92 Merge pull request #223 from haberman/timestamp
88b1026d26 Fixed leap year handling by reworking upb_mktime() -> upb_timegm().
715718d5a5 Changed endsubmsg handler to return the closure of the submessage.
56589c7276 Merge pull request #219 from haberman/asan
1ed64db8c2 Fixed compiler error "error: control reaches end of non-void function".
32bed8562a Merge pull request #217 from haberman/fix-bazel
5768e68ed7 Fixed for Bazel >= 1.0.

git-subtree-dir: third_party/upb
git-subtree-split: 8a3ae1ef3e3e3f26b45dec735c5776737fc7247f
---
 bazel/upb_proto_library.bzl           |   7 +-
 bazel/workspace_deps.bzl              |   4 +-
 generated_for_cmake/upb/json/parser.c | 210 ++++++++++++--------------
 tests/pb/test_decoder.cc              |  24 +--
 upb/decode.c                          |   1 +
 upb/json/parser.rl                    |  72 ++++-----
 upb/pb/decoder.c                      |   3 +-
 upb/sink.h                            |  11 +-
 8 files changed, 156 insertions(+), 176 deletions(-)

diff --git a/bazel/upb_proto_library.bzl b/bazel/upb_proto_library.bzl
index cc6bcffaede..f148745be5e 100644
--- a/bazel/upb_proto_library.bzl
+++ b/bazel/upb_proto_library.bzl
@@ -22,6 +22,11 @@ def _get_real_short_path(file):
     if short_path.startswith("../"):
         second_slash = short_path.index("/", 3)
         short_path = short_path[second_slash + 1:]
+    # Sometimes it has another few prefixes like:
+    #   _virtual_imports/any_proto/google/protobuf/any.proto
+    # We want just google/protobuf/any.proto.
+    if short_path.startswith("_virtual_imports"):
+        short_path = short_path.split("/", 2)[-1]
     return short_path
 
 def _get_real_root(file):
@@ -175,7 +180,7 @@ def _upb_proto_rule_impl(ctx):
              "_WrappedGeneratedSrcsInfo (aspect should have handled this).")
     cc_info = dep[_WrappedCcInfo].cc_info
     srcs = dep[_WrappedGeneratedSrcsInfo].srcs
-    if (type(cc_info.linking_context.libraries_to_link) == "list"):
+    if type(cc_info.linking_context.libraries_to_link) == "list":
         lib = cc_info.linking_context.libraries_to_link[0]
     else:
         lib = cc_info.linking_context.libraries_to_link.to_list()[0]
diff --git a/bazel/workspace_deps.bzl b/bazel/workspace_deps.bzl
index 39bf524a7a1..7dbd761d057 100644
--- a/bazel/workspace_deps.bzl
+++ b/bazel/workspace_deps.bzl
@@ -30,7 +30,7 @@ def upb_deps():
     http_archive(
         name = "zlib",
         build_file = "@com_google_protobuf//:third_party/zlib.BUILD",
-        sha256 = "c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1",
+        sha256 = "629380c90a77b964d896ed37163f5c3a34f6e6d897311f1df2a7016355c45eff",
         strip_prefix = "zlib-1.2.11",
-        urls = ["https://zlib.net/zlib-1.2.11.tar.gz"],
+        url = "https://github.com/madler/zlib/archive/v1.2.11.tar.gz",
     )
diff --git a/generated_for_cmake/upb/json/parser.c b/generated_for_cmake/upb/json/parser.c
index f72e945881f..9955a024aa9 100644
--- a/generated_for_cmake/upb/json/parser.c
+++ b/generated_for_cmake/upb/json/parser.c
@@ -1689,46 +1689,32 @@ static void start_timestamp_zone(upb_json_parser *p, const char *ptr) {
   capture_begin(p, ptr);
 }
 
-#define EPOCH_YEAR 1970
-#define TM_YEAR_BASE 1900
-
-static bool isleap(int year) {
-  return (year % 4) == 0 && (year % 100 != 0 || (year % 400) == 0);
-}
-
-const unsigned short int __mon_yday[2][13] = {
-    /* Normal years.  */
-    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
-    /* Leap years.  */
-    { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
-};
-
-int64_t epoch(int year, int yday, int hour, int min, int sec) {
-  int64_t years = year - EPOCH_YEAR;
-
-  int64_t leap_days = years / 4 - years / 100 + years / 400;
-
-  int64_t days = years * 365 + yday + leap_days;
-  int64_t hours = days * 24 + hour;
-  int64_t mins = hours * 60 + min;
-  int64_t secs = mins * 60 + sec;
-  return secs;
-}
-
-
-static int64_t upb_mktime(const struct tm *tp) {
-  int sec = tp->tm_sec;
-  int min = tp->tm_min;
-  int hour = tp->tm_hour;
-  int mday = tp->tm_mday;
-  int mon = tp->tm_mon;
-  int year = tp->tm_year + TM_YEAR_BASE;
-
-  /* Calculate day of year from year, month, and day of month. */
-  int mon_yday = ((__mon_yday[isleap(year)][mon]) - 1);
-  int yday = mon_yday + mday;
-
-  return epoch(year, yday, hour, min, sec);
+static int div_round_up2(int n, int d) {
+  return (n + d - 1) / d;
+}
+
+/* epoch_days(1970, 1, 1) == 1970-01-01 == 0. */
+static int epoch_days(int year, int month, int day) {
+  static const uint16_t month_yday[12] = {0,   31,  59,  90,  120, 151,
+                                          181, 212, 243, 273, 304, 334};
+  int febs_since_0 = month > 2 ? year + 1 : year;
+  int leap_days_since_0 = div_round_up2(febs_since_0, 4) -
+                          div_round_up2(febs_since_0, 100) +
+                          div_round_up2(febs_since_0, 400);
+  int days_since_0 =
+      365 * year + month_yday[month - 1] + (day - 1) + leap_days_since_0;
+
+  /* Convert from 0-epoch (0001-01-01 BC) to Unix Epoch (1970-01-01 AD).
+   * Since the "BC" system does not have a year zero, 1 BC == year zero. */
+  return days_since_0 - 719528;
+}
+
+static int64_t upb_timegm(const struct tm *tp) {
+  int64_t ret = epoch_days(tp->tm_year + 1900, tp->tm_mon + 1, tp->tm_mday);
+  ret = (ret * 24) + tp->tm_hour;
+  ret = (ret * 60) + tp->tm_min;
+  ret = (ret * 60) + tp->tm_sec;
+  return ret;
 }
 
 static bool end_timestamp_zone(upb_json_parser *p, const char *ptr) {
@@ -1758,7 +1744,7 @@ static bool end_timestamp_zone(upb_json_parser *p, const char *ptr) {
   }
 
   /* Normalize tm */
-  seconds = upb_mktime(&p->tm);
+  seconds = upb_timegm(&p->tm);
 
   /* Check timestamp boundary */
   if (seconds < -62135596800) {
@@ -2036,7 +2022,7 @@ static void end_member(upb_json_parser *p) {
     p->top--;
     ok = upb_handlers_getselector(mapfield, UPB_HANDLER_ENDSUBMSG, &sel);
     UPB_ASSERT(ok);
-    upb_sink_endsubmsg(p->top->sink, sel);
+    upb_sink_endsubmsg(p->top->sink, (p->top + 1)->sink, sel);
   }
 
   p->top->f = NULL;
@@ -2150,7 +2136,7 @@ static void end_subobject(upb_json_parser *p) {
     p->top--;
     if (!is_unknown) {
       sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSUBMSG);
-      upb_sink_endsubmsg(p->top->sink, sel);
+      upb_sink_endsubmsg(p->top->sink, (p->top + 1)->sink, sel);
     }
   }
 }
@@ -2589,11 +2575,11 @@ static bool does_fieldmask_end(upb_json_parser *p) {
  * final state once, when the closing '"' is seen. */
 
 
-#line 2794 "upb/json/parser.rl"
+#line 2780 "upb/json/parser.rl"
 
 
 
-#line 2597 "upb/json/parser.c"
+#line 2583 "upb/json/parser.c"
 static const char _json_actions[] = {
 	0, 1, 0, 1, 1, 1, 3, 1, 
 	4, 1, 6, 1, 7, 1, 8, 1, 
@@ -2848,7 +2834,7 @@ static const int json_en_value_machine = 78;
 static const int json_en_main = 1;
 
 
-#line 2797 "upb/json/parser.rl"
+#line 2783 "upb/json/parser.rl"
 
 size_t parse(void *closure, const void *hd, const char *buf, size_t size,
              const upb_bufhandle *handle) {
@@ -2871,7 +2857,7 @@ size_t parse(void *closure, const void *hd, const char *buf, size_t size,
   capture_resume(parser, buf);
 
   
-#line 2875 "upb/json/parser.c"
+#line 2861 "upb/json/parser.c"
 	{
 	int _klen;
 	unsigned int _trans;
@@ -2946,147 +2932,147 @@ _match:
 		switch ( *_acts++ )
 		{
 	case 1:
-#line 2602 "upb/json/parser.rl"
+#line 2588 "upb/json/parser.rl"
 	{ p--; {cs = stack[--top]; goto _again;} }
 	break;
 	case 2:
-#line 2604 "upb/json/parser.rl"
+#line 2590 "upb/json/parser.rl"
 	{ p--; {stack[top++] = cs; cs = 23;goto _again;} }
 	break;
 	case 3:
-#line 2608 "upb/json/parser.rl"
+#line 2594 "upb/json/parser.rl"
 	{ start_text(parser, p); }
 	break;
 	case 4:
-#line 2609 "upb/json/parser.rl"
+#line 2595 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(end_text(parser, p)); }
 	break;
 	case 5:
-#line 2615 "upb/json/parser.rl"
+#line 2601 "upb/json/parser.rl"
 	{ start_hex(parser); }
 	break;
 	case 6:
-#line 2616 "upb/json/parser.rl"
+#line 2602 "upb/json/parser.rl"
 	{ hexdigit(parser, p); }
 	break;
 	case 7:
-#line 2617 "upb/json/parser.rl"
+#line 2603 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(end_hex(parser)); }
 	break;
 	case 8:
-#line 2623 "upb/json/parser.rl"
+#line 2609 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(escape(parser, p)); }
 	break;
 	case 9:
-#line 2629 "upb/json/parser.rl"
+#line 2615 "upb/json/parser.rl"
 	{ p--; {cs = stack[--top]; goto _again;} }
 	break;
 	case 10:
-#line 2634 "upb/json/parser.rl"
+#line 2620 "upb/json/parser.rl"
 	{ start_year(parser, p); }
 	break;
 	case 11:
-#line 2635 "upb/json/parser.rl"
+#line 2621 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(end_year(parser, p)); }
 	break;
 	case 12:
-#line 2639 "upb/json/parser.rl"
+#line 2625 "upb/json/parser.rl"
 	{ start_month(parser, p); }
 	break;
 	case 13:
-#line 2640 "upb/json/parser.rl"
+#line 2626 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(end_month(parser, p)); }
 	break;
 	case 14:
-#line 2644 "upb/json/parser.rl"
+#line 2630 "upb/json/parser.rl"
 	{ start_day(parser, p); }
 	break;
 	case 15:
-#line 2645 "upb/json/parser.rl"
+#line 2631 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(end_day(parser, p)); }
 	break;
 	case 16:
-#line 2649 "upb/json/parser.rl"
+#line 2635 "upb/json/parser.rl"
 	{ start_hour(parser, p); }
 	break;
 	case 17:
-#line 2650 "upb/json/parser.rl"
+#line 2636 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(end_hour(parser, p)); }
 	break;
 	case 18:
-#line 2654 "upb/json/parser.rl"
+#line 2640 "upb/json/parser.rl"
 	{ start_minute(parser, p); }
 	break;
 	case 19:
-#line 2655 "upb/json/parser.rl"
+#line 2641 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(end_minute(parser, p)); }
 	break;
 	case 20:
-#line 2659 "upb/json/parser.rl"
+#line 2645 "upb/json/parser.rl"
 	{ start_second(parser, p); }
 	break;
 	case 21:
-#line 2660 "upb/json/parser.rl"
+#line 2646 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(end_second(parser, p)); }
 	break;
 	case 22:
-#line 2665 "upb/json/parser.rl"
+#line 2651 "upb/json/parser.rl"
 	{ start_duration_base(parser, p); }
 	break;
 	case 23:
-#line 2666 "upb/json/parser.rl"
+#line 2652 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(end_duration_base(parser, p)); }
 	break;
 	case 24:
-#line 2668 "upb/json/parser.rl"
+#line 2654 "upb/json/parser.rl"
 	{ p--; {cs = stack[--top]; goto _again;} }
 	break;
 	case 25:
-#line 2673 "upb/json/parser.rl"
+#line 2659 "upb/json/parser.rl"
 	{ start_timestamp_base(parser); }
 	break;
 	case 26:
-#line 2675 "upb/json/parser.rl"
+#line 2661 "upb/json/parser.rl"
 	{ start_timestamp_fraction(parser, p); }
 	break;
 	case 27:
-#line 2676 "upb/json/parser.rl"
+#line 2662 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(end_timestamp_fraction(parser, p)); }
 	break;
 	case 28:
-#line 2678 "upb/json/parser.rl"
+#line 2664 "upb/json/parser.rl"
 	{ start_timestamp_zone(parser, p); }
 	break;
 	case 29:
-#line 2679 "upb/json/parser.rl"
+#line 2665 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(end_timestamp_zone(parser, p)); }
 	break;
 	case 30:
-#line 2681 "upb/json/parser.rl"
+#line 2667 "upb/json/parser.rl"
 	{ p--; {cs = stack[--top]; goto _again;} }
 	break;
 	case 31:
-#line 2686 "upb/json/parser.rl"
+#line 2672 "upb/json/parser.rl"
 	{ start_fieldmask_path_text(parser, p); }
 	break;
 	case 32:
-#line 2687 "upb/json/parser.rl"
+#line 2673 "upb/json/parser.rl"
 	{ end_fieldmask_path_text(parser, p); }
 	break;
 	case 33:
-#line 2692 "upb/json/parser.rl"
+#line 2678 "upb/json/parser.rl"
 	{ start_fieldmask_path(parser); }
 	break;
 	case 34:
-#line 2693 "upb/json/parser.rl"
+#line 2679 "upb/json/parser.rl"
 	{ end_fieldmask_path(parser); }
 	break;
 	case 35:
-#line 2699 "upb/json/parser.rl"
+#line 2685 "upb/json/parser.rl"
 	{ p--; {cs = stack[--top]; goto _again;} }
 	break;
 	case 36:
-#line 2704 "upb/json/parser.rl"
+#line 2690 "upb/json/parser.rl"
 	{
         if (is_wellknown_msg(parser, UPB_WELLKNOWN_TIMESTAMP)) {
           {stack[top++] = cs; cs = 47;goto _again;}
@@ -3100,11 +3086,11 @@ _match:
       }
 	break;
 	case 37:
-#line 2717 "upb/json/parser.rl"
+#line 2703 "upb/json/parser.rl"
 	{ p--; {stack[top++] = cs; cs = 78;goto _again;} }
 	break;
 	case 38:
-#line 2722 "upb/json/parser.rl"
+#line 2708 "upb/json/parser.rl"
 	{
         if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
           start_any_member(parser, p);
@@ -3114,11 +3100,11 @@ _match:
       }
 	break;
 	case 39:
-#line 2729 "upb/json/parser.rl"
+#line 2715 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(end_membername(parser)); }
 	break;
 	case 40:
-#line 2732 "upb/json/parser.rl"
+#line 2718 "upb/json/parser.rl"
 	{
         if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
           end_any_member(parser, p);
@@ -3128,7 +3114,7 @@ _match:
       }
 	break;
 	case 41:
-#line 2743 "upb/json/parser.rl"
+#line 2729 "upb/json/parser.rl"
 	{
         if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
           start_any_object(parser, p);
@@ -3138,7 +3124,7 @@ _match:
       }
 	break;
 	case 42:
-#line 2752 "upb/json/parser.rl"
+#line 2738 "upb/json/parser.rl"
 	{
         if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
           CHECK_RETURN_TOP(end_any_object(parser, p));
@@ -3148,54 +3134,54 @@ _match:
       }
 	break;
 	case 43:
-#line 2764 "upb/json/parser.rl"
+#line 2750 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(start_array(parser)); }
 	break;
 	case 44:
-#line 2768 "upb/json/parser.rl"
+#line 2754 "upb/json/parser.rl"
 	{ end_array(parser); }
 	break;
 	case 45:
-#line 2773 "upb/json/parser.rl"
+#line 2759 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(start_number(parser, p)); }
 	break;
 	case 46:
-#line 2774 "upb/json/parser.rl"
+#line 2760 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(end_number(parser, p)); }
 	break;
 	case 47:
-#line 2776 "upb/json/parser.rl"
+#line 2762 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(start_stringval(parser)); }
 	break;
 	case 48:
-#line 2777 "upb/json/parser.rl"
+#line 2763 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(end_stringval(parser)); }
 	break;
 	case 49:
-#line 2779 "upb/json/parser.rl"
+#line 2765 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(end_bool(parser, true)); }
 	break;
 	case 50:
-#line 2781 "upb/json/parser.rl"
+#line 2767 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(end_bool(parser, false)); }
 	break;
 	case 51:
-#line 2783 "upb/json/parser.rl"
+#line 2769 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(end_null(parser)); }
 	break;
 	case 52:
-#line 2785 "upb/json/parser.rl"
+#line 2771 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(start_subobject_full(parser)); }
 	break;
 	case 53:
-#line 2786 "upb/json/parser.rl"
+#line 2772 "upb/json/parser.rl"
 	{ end_subobject_full(parser); }
 	break;
 	case 54:
-#line 2791 "upb/json/parser.rl"
+#line 2777 "upb/json/parser.rl"
 	{ p--; {cs = stack[--top]; goto _again;} }
 	break;
-#line 3199 "upb/json/parser.c"
+#line 3185 "upb/json/parser.c"
 		}
 	}
 
@@ -3212,32 +3198,32 @@ _again:
 	while ( __nacts-- > 0 ) {
 		switch ( *__acts++ ) {
 	case 0:
-#line 2600 "upb/json/parser.rl"
+#line 2586 "upb/json/parser.rl"
 	{ p--; {cs = stack[--top]; 	if ( p == pe )
 		goto _test_eof;
 goto _again;} }
 	break;
 	case 46:
-#line 2774 "upb/json/parser.rl"
+#line 2760 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(end_number(parser, p)); }
 	break;
 	case 49:
-#line 2779 "upb/json/parser.rl"
+#line 2765 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(end_bool(parser, true)); }
 	break;
 	case 50:
-#line 2781 "upb/json/parser.rl"
+#line 2767 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(end_bool(parser, false)); }
 	break;
 	case 51:
-#line 2783 "upb/json/parser.rl"
+#line 2769 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(end_null(parser)); }
 	break;
 	case 53:
-#line 2786 "upb/json/parser.rl"
+#line 2772 "upb/json/parser.rl"
 	{ end_subobject_full(parser); }
 	break;
-#line 3241 "upb/json/parser.c"
+#line 3227 "upb/json/parser.c"
 		}
 	}
 	}
@@ -3245,7 +3231,7 @@ goto _again;} }
 	_out: {}
 	}
 
-#line 2819 "upb/json/parser.rl"
+#line 2805 "upb/json/parser.rl"
 
   if (p != pe) {
     upb_status_seterrf(parser->status, "Parse error at '%.*s'\n", pe - p, p);
@@ -3288,13 +3274,13 @@ static void json_parser_reset(upb_json_parser *p) {
 
   /* Emit Ragel initialization of the parser. */
   
-#line 3292 "upb/json/parser.c"
+#line 3278 "upb/json/parser.c"
 	{
 	cs = json_start;
 	top = 0;
 	}
 
-#line 2861 "upb/json/parser.rl"
+#line 2847 "upb/json/parser.rl"
   p->current_state = cs;
   p->parser_top = top;
   accumulate_clear(p);
diff --git a/tests/pb/test_decoder.cc b/tests/pb/test_decoder.cc
index 5cc59e40c92..ef40f8f3e26 100644
--- a/tests/pb/test_decoder.cc
+++ b/tests/pb/test_decoder.cc
@@ -569,7 +569,7 @@ string wrap_text(int32_t fn, const string& text) {
       LINE("<"),
       num2string(fn), LINE(":{")
       "  ", wrapped_text,
-      LINE("}")
+      LINE("  }")
       LINE(">"));
   return wrapped_text;
 }
@@ -922,7 +922,7 @@ void test_valid() {
       LINE("%u:{")
       LINE("  <")
       LINE("  >")
-      LINE("}")
+      LINE("  }")
       LINE(">"), UPB_DESCRIPTOR_TYPE_MESSAGE);
 
   assert_successful_parse(
@@ -933,7 +933,7 @@ void test_valid() {
       LINE("%u:{")
       LINE("  <")
       LINE("  >")
-      LINE("}")
+      LINE("  }")
       LINE("%u:5")
       LINE(">"), UPB_DESCRIPTOR_TYPE_MESSAGE, UPB_DESCRIPTOR_TYPE_INT32);
 
@@ -957,9 +957,9 @@ void test_valid() {
       LINE("    <")
       LINE("    %u:2345678")
       LINE("    >")
-      LINE("  }")
+      LINE("    }")
       LINE("  >")
-      LINE("}")
+      LINE("  }")
       LINE("%u:22222")
       LINE(">"), msg_type, msg_type, int32_type, int32_type);
 
@@ -984,7 +984,7 @@ void test_valid() {
       LINE("  %u:(5)\"abcde")
       LINE("    %u:\"")
       LINE("  >")
-      LINE("}")
+      LINE("  }")
       LINE(">"), msg_fn, UPB_DESCRIPTOR_TYPE_STRING,
                  UPB_DESCRIPTOR_TYPE_STRING);
 
@@ -1014,11 +1014,11 @@ void test_valid() {
       LINE("    %u:{")
       LINE("      <")
       LINE("      >")
-      LINE("    }")
+      LINE("      }")
       LINE("    >")
-      LINE("  }")
+      LINE("    }")
       LINE("  >")
-      LINE("}")
+      LINE("  }")
       LINE(">"), msg_fn, msg_fn, msg_fn);
 
   uint32_t repm_fn = rep_fn(UPB_DESCRIPTOR_TYPE_MESSAGE);
@@ -1032,10 +1032,10 @@ void test_valid() {
       LINE("      %u:{")
       LINE("        <")
       LINE("        >")
-      LINE("      }")
+      LINE("        }")
       LINE("    ]")
       LINE("    >")
-      LINE("  }")
+      LINE("    }")
       LINE("]")
       LINE(">"), repm_fn, repm_fn, repm_fn, repm_fn);
 
@@ -1099,7 +1099,7 @@ void test_valid() {
   textbuf.append(">\n");
   for (int i = 0; i < total; i++) {
     indentbuf(&textbuf, total - i - 1);
-    textbuf.append("}\n");
+    textbuf.append("  }\n");
     indentbuf(&textbuf, total - i - 1);
     textbuf.append(">\n");
   }
diff --git a/upb/decode.c b/upb/decode.c
index 88d4bb4fb6d..4f079885950 100644
--- a/upb/decode.c
+++ b/upb/decode.c
@@ -573,6 +573,7 @@ static bool upb_decode_field(upb_decstate *d, upb_decframe *frame) {
     CHK(upb_append_unknown(d, frame));
     return true;
   }
+  UPB_UNREACHABLE();
 }
 
 static bool upb_decode_message(upb_decstate *d, char *msg, const upb_msglayout *l) {
diff --git a/upb/json/parser.rl b/upb/json/parser.rl
index 2641dda31c3..1180ce137f8 100644
--- a/upb/json/parser.rl
+++ b/upb/json/parser.rl
@@ -1687,46 +1687,32 @@ static void start_timestamp_zone(upb_json_parser *p, const char *ptr) {
   capture_begin(p, ptr);
 }
 
-#define EPOCH_YEAR 1970
-#define TM_YEAR_BASE 1900
-
-static bool isleap(int year) {
-  return (year % 4) == 0 && (year % 100 != 0 || (year % 400) == 0);
-}
-
-const unsigned short int __mon_yday[2][13] = {
-    /* Normal years.  */
-    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
-    /* Leap years.  */
-    { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
-};
-
-int64_t epoch(int year, int yday, int hour, int min, int sec) {
-  int64_t years = year - EPOCH_YEAR;
-
-  int64_t leap_days = years / 4 - years / 100 + years / 400;
-
-  int64_t days = years * 365 + yday + leap_days;
-  int64_t hours = days * 24 + hour;
-  int64_t mins = hours * 60 + min;
-  int64_t secs = mins * 60 + sec;
-  return secs;
-}
-
-
-static int64_t upb_mktime(const struct tm *tp) {
-  int sec = tp->tm_sec;
-  int min = tp->tm_min;
-  int hour = tp->tm_hour;
-  int mday = tp->tm_mday;
-  int mon = tp->tm_mon;
-  int year = tp->tm_year + TM_YEAR_BASE;
-
-  /* Calculate day of year from year, month, and day of month. */
-  int mon_yday = ((__mon_yday[isleap(year)][mon]) - 1);
-  int yday = mon_yday + mday;
-
-  return epoch(year, yday, hour, min, sec);
+static int div_round_up2(int n, int d) {
+  return (n + d - 1) / d;
+}
+
+/* epoch_days(1970, 1, 1) == 1970-01-01 == 0. */
+static int epoch_days(int year, int month, int day) {
+  static const uint16_t month_yday[12] = {0,   31,  59,  90,  120, 151,
+                                          181, 212, 243, 273, 304, 334};
+  int febs_since_0 = month > 2 ? year + 1 : year;
+  int leap_days_since_0 = div_round_up2(febs_since_0, 4) -
+                          div_round_up2(febs_since_0, 100) +
+                          div_round_up2(febs_since_0, 400);
+  int days_since_0 =
+      365 * year + month_yday[month - 1] + (day - 1) + leap_days_since_0;
+
+  /* Convert from 0-epoch (0001-01-01 BC) to Unix Epoch (1970-01-01 AD).
+   * Since the "BC" system does not have a year zero, 1 BC == year zero. */
+  return days_since_0 - 719528;
+}
+
+static int64_t upb_timegm(const struct tm *tp) {
+  int64_t ret = epoch_days(tp->tm_year + 1900, tp->tm_mon + 1, tp->tm_mday);
+  ret = (ret * 24) + tp->tm_hour;
+  ret = (ret * 60) + tp->tm_min;
+  ret = (ret * 60) + tp->tm_sec;
+  return ret;
 }
 
 static bool end_timestamp_zone(upb_json_parser *p, const char *ptr) {
@@ -1756,7 +1742,7 @@ static bool end_timestamp_zone(upb_json_parser *p, const char *ptr) {
   }
 
   /* Normalize tm */
-  seconds = upb_mktime(&p->tm);
+  seconds = upb_timegm(&p->tm);
 
   /* Check timestamp boundary */
   if (seconds < -62135596800) {
@@ -2034,7 +2020,7 @@ static void end_member(upb_json_parser *p) {
     p->top--;
     ok = upb_handlers_getselector(mapfield, UPB_HANDLER_ENDSUBMSG, &sel);
     UPB_ASSERT(ok);
-    upb_sink_endsubmsg(p->top->sink, sel);
+    upb_sink_endsubmsg(p->top->sink, (p->top + 1)->sink, sel);
   }
 
   p->top->f = NULL;
@@ -2148,7 +2134,7 @@ static void end_subobject(upb_json_parser *p) {
     p->top--;
     if (!is_unknown) {
       sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSUBMSG);
-      upb_sink_endsubmsg(p->top->sink, sel);
+      upb_sink_endsubmsg(p->top->sink, (p->top + 1)->sink, sel);
     }
   }
 }
diff --git a/upb/pb/decoder.c b/upb/pb/decoder.c
index 735bef18f8e..ba2b7700981 100644
--- a/upb/pb/decoder.c
+++ b/upb/pb/decoder.c
@@ -749,7 +749,8 @@ size_t run_decoder_vm(upb_pbdecoder *d, const mgroup *group,
         CHECK_SUSPEND(upb_sink_startsubmsg(outer->sink, arg, &d->top->sink));
       )
       VMCASE(OP_ENDSUBMSG,
-        CHECK_SUSPEND(upb_sink_endsubmsg(d->top->sink, arg));
+        upb_sink subsink = (d->top + 1)->sink;
+        CHECK_SUSPEND(upb_sink_endsubmsg(d->top->sink, subsink, arg));
       )
       VMCASE(OP_STARTSTR,
         uint32_t len = delim_remaining(d);
diff --git a/upb/sink.h b/upb/sink.h
index 47d218a9c1b..871a8f57a70 100644
--- a/upb/sink.h
+++ b/upb/sink.h
@@ -185,15 +185,16 @@ UPB_INLINE bool upb_sink_startsubmsg(upb_sink s, upb_selector_t sel,
   return sub->closure ? true : false;
 }
 
-UPB_INLINE bool upb_sink_endsubmsg(upb_sink s, upb_selector_t sel) {
+UPB_INLINE bool upb_sink_endsubmsg(upb_sink s, upb_sink sub,
+                                   upb_selector_t sel) {
   typedef upb_endfield_handlerfunc func;
   func *endsubmsg;
   const void *hd;
   if (!s.handlers) return true;
   endsubmsg = (func*)upb_handlers_gethandler(s.handlers, sel, &hd);
 
-  if (!endsubmsg) return s.closure;
-  return endsubmsg(s.closure, hd);
+  if (!endsubmsg) return true;
+  return endsubmsg(sub.closure, hd);
 }
 
 #ifdef __cplusplus
@@ -359,8 +360,8 @@ class upb::Sink {
     return ret;
   }
 
-  bool EndSubMessage(HandlersPtr::Selector s) {
-    return upb_sink_endsubmsg(sink_, s);
+  bool EndSubMessage(HandlersPtr::Selector s, Sink sub) {
+    return upb_sink_endsubmsg(sink_, sub.sink_, s);
   }
 
   /* For repeated fields of any type, the sequence of values must be wrapped in