diff --git a/source/texk/web2c/luatexdir/tex/mlist.w b/source/texk/web2c/luatexdir/tex/mlist.w
index 4c1f5dc..c765074 100644
--- a/source/texk/web2c/luatexdir/tex/mlist.w
+++ b/source/texk/web2c/luatexdir/tex/mlist.w
@@ -2131,23 +2131,22 @@ respect to the size of the final box.
 @c
 #define TOP_CODE 1
 #define BOT_CODE 2
-#define TOP_OR_BOT_MASK ((TOP_CODE) | (BOT_CODE))
-#define STRETCH_ACCENT_CODE 4
+#define OVERLAY_CODE 4
+#define STRETCH_ACCENT_CODE 8
 
 static void do_make_math_accent(pointer q, internal_font_number f, int c,
                                 int flags, int cur_style)
 {
     pointer p, r, x, y;         /* temporary registers for box construction */
     scaled s;                   /* amount to skew the accent to the right */
-    scaled h;                   /* height of character being accented */
-    scaled delta;               /* space to remove between accent and accentee */
+    scaled h;                   /* height of the accentee */
     scaled w;                   /* width of the accentee, not including sub/superscripts */
+    scaled delta;               /* space to remove between accent and accentee */
     boolean s_is_absolute;      /* will be true if a top-accent is placed in |s| */
     extinfo *ext;
     pointer attr_p;
     const int compat_mode = radical_rule(cur_style) == undefined_math_parameter;
-    const int top_or_bot = flags & TOP_OR_BOT_MASK;
-    attr_p = (top_or_bot == TOP_CODE ? accent_chr(q) : bot_accent_chr(q));
+    attr_p = (flags & TOP_CODE ? accent_chr(q) : flags & BOT_CODE ? bot_accent_chr(q) : overlay_accent_chr(q));
     s_is_absolute = false;
     c = cur_c;
     f = cur_f;
@@ -2156,13 +2155,13 @@ static void do_make_math_accent(pointer q, internal_font_number f, int c,
     if (type(nucleus(q)) == math_char_node) {
         fetch(nucleus(q));
         if (compat_mode) {
-          if (top_or_bot == TOP_CODE) {
+          if (flags & TOP_CODE) {
             s = get_kern(cur_f, cur_c, skew_char(cur_f));
           } else {
             s = 0;
           }
         } else {
-        if (top_or_bot == TOP_CODE) {
+        if (flags & (TOP_CODE | OVERLAY_CODE)) {
             s = char_top_accent(cur_f, cur_c);
             if (s != INT_MIN) {
                 s_is_absolute = true;
@@ -2203,8 +2202,15 @@ static void do_make_math_accent(pointer q, internal_font_number f, int c,
             int yy = char_remainder(f, c);
             if (!char_exists(f, yy))
                 break;
-            if (char_width(f, yy) > w)
-                break;
+            if (flags & OVERLAY_CODE) {
+                if ((.90 * char_height(f, yy)) > h) { /* make sure the accent is a bit larger than the accentee */
+                   c = yy;
+                   break;
+                }
+            } else {
+                if (char_width(f, yy) > w)
+                   break;
+            }
             c = yy;
         }
       }
@@ -2212,11 +2218,13 @@ static void do_make_math_accent(pointer q, internal_font_number f, int c,
     if (y == null) {
         y = char_box(f, c, node_attr(attr_p));
     }
-    if (top_or_bot == TOP_CODE) {
+    if (flags & TOP_CODE) {
         if (h < accent_base_height(f))
             delta = h;
         else
             delta = accent_base_height(f);
+    } else if (flags & OVERLAY_CODE) {
+        delta = half(height(y)+depth(y)+height(x)+depth(x)); /* center the accent vertically around the accentee */
     } else {
         delta = 0;              /* hm */
     }
@@ -2240,7 +2248,7 @@ static void do_make_math_accent(pointer q, internal_font_number f, int c,
     }
     if (s_is_absolute) {
         scaled sa;
-        if (top_or_bot == TOP_CODE)
+        if (flags & (TOP_CODE | OVERLAY_CODE))
             sa = char_top_accent(f, c);
         else
             sa = char_bot_accent(f, c);
@@ -2256,7 +2264,7 @@ static void do_make_math_accent(pointer q, internal_font_number f, int c,
         }
     }
     width(y) = 0;
-    if (top_or_bot == TOP_CODE) {
+    if (flags & (TOP_CODE | OVERLAY_CODE)) {
         p = new_kern(-delta);
         vlink(p) = x;
         vlink(y) = p;
@@ -2274,7 +2282,7 @@ static void do_make_math_accent(pointer q, internal_font_number f, int c,
     reset_attributes(r, node_attr(q));
     width(r) = width(x);
     y = r;
-    if (top_or_bot == TOP_CODE) {
+    if (flags & TOP_CODE) {
         if (height(y) < h) {
             /* Make the height of box |y| equal to |h| */
             p = new_kern(h - height(y));
@@ -2283,7 +2291,7 @@ static void do_make_math_accent(pointer q, internal_font_number f, int c,
             list_ptr(y) = p;
             height(y) = h;
         }
-    } else {
+    } else if (flags & BOT_CODE) {
         shift_amount(y) = -(h - height(y));
     }
     math_list(nucleus(q)) = y;
@@ -2311,6 +2319,14 @@ static void make_math_accent(pointer q, int cur_style)
         flush_node(bot_accent_chr(q));
         bot_accent_chr(q) = null;
     }
+    if (overlay_accent_chr(q) != null) {
+        fetch(overlay_accent_chr(q));
+        if (char_exists(cur_f, cur_c)) {
+          do_make_math_accent(q, cur_f, cur_c, OVERLAY_CODE | STRETCH_ACCENT_CODE, cur_style);
+        }
+        flush_node(overlay_accent_chr(q));
+        overlay_accent_chr(q) = null;
+    }
 }
 
 @ The |make_fraction| procedure is a bit different because it sets
diff --git a/source/texk/web2c/luatexdir/tex/texmath.w b/source/texk/web2c/luatexdir/tex/texmath.w
index bcde1ee..25d86fc 100644
--- a/source/texk/web2c/luatexdir/tex/texmath.w
+++ b/source/texk/web2c/luatexdir/tex/texmath.w
@@ -721,8 +721,10 @@ void display_normal_noad(pointer p)
            } else {
                tprint_esc("Umathaccent");
            }
-       } else {
+       } else if (bot_accent_chr(p) != null) {
            tprint_esc("Umathaccent bottom");
+       } else {
+           tprint_esc("Umathaccent overlay");
        }
        switch (subtype(p)) {
        case 0:
@@ -733,8 +735,10 @@ void display_normal_noad(pointer p)
             } else {
                 print_fam_and_char(accent_chr(p));
             }
-        } else {
+        } else if (bot_accent_chr(p) != null) {
             print_fam_and_char(bot_accent_chr(p));
+        } else {
+            print_fam_and_char(overlay_accent_chr(p));
         }
         break;
        case 1:
@@ -1582,8 +1586,7 @@ void math_radical(void)
 void math_ac(void)
 {
     halfword q;
-    mathcodeval t = { 0, 0, 0, 0 }, b = {
-    0, 0, 0, 0};
+    mathcodeval t = { 0, 0, 0, 0 }, b = { 0, 0, 0, 0 }, o = { 0, 0, 0, 0 };
     if (cur_cmd == accent_cmd) {
         const char *hlp[] = {
             "I'm changing \\accent to \\mathaccent here; wish me luck.",
@@ -1615,6 +1618,8 @@ void math_ac(void)
              subtype(tail) = 2;
            }
 	   b = scan_mathchar(xetex_mathcode);
+	} else if (scan_keyword("overlay")) {
+	   o = scan_mathchar(xetex_mathcode);
 	} else {
 	   t = scan_mathchar(xetex_mathcode);
 	}
@@ -1646,6 +1651,15 @@ void math_ac(void)
         else
             math_fam(bot_accent_chr(tail)) = b.family_value;
     }
+    if (!(o.character_value == 0 && o.family_value == 0)) {
+        q = new_node(math_char_node, 0);
+        overlay_accent_chr(tail) = q;
+        math_character(overlay_accent_chr(tail)) = o.character_value;
+        if ((o.class_value == var_code) && fam_in_range)
+            math_fam(overlay_accent_chr(tail)) = cur_fam;
+        else
+            math_fam(overlay_accent_chr(tail)) = o.family_value;
+    }
     q = new_node(math_char_node, 0);
     nucleus(tail) = q;
     (void) scan_math(nucleus(tail), cramped_style(m_style));
diff --git a/source/texk/web2c/luatexdir/tex/texnodes.h b/source/texk/web2c/luatexdir/tex/texnodes.h
index ddbcb41..50449d3 100644
--- a/source/texk/web2c/luatexdir/tex/texnodes.h
+++ b/source/texk/web2c/luatexdir/tex/texnodes.h
@@ -381,9 +381,10 @@ typedef enum {
 /* accent noads */
 /* like a regular noad, but with two extra fields. */
 
-#  define accent_noad_size 5    /*number of |mem| words in an accent noad */
+#  define accent_noad_size 6    /*number of |mem| words in an accent noad */
 #  define accent_chr(a) vinfo((a)+4)    /* the |accent_chr| field of an accent noad */
 #  define bot_accent_chr(a) vlink((a)+4)        /* the |bot_accent_chr| field of an accent noad */
+#  define overlay_accent_chr(a) vinfo((a)+5)    /* the |overlay_accent_chr| field of an accent noad */
 
 /* left and right noads */
 
diff --git a/source/texk/web2c/luatexdir/tex/texnodes.w b/source/texk/web2c/luatexdir/tex/texnodes.w
index a661dcf..ef990b9 100644
--- a/source/texk/web2c/luatexdir/tex/texnodes.w
+++ b/source/texk/web2c/luatexdir/tex/texnodes.w
@@ -610,6 +610,8 @@ halfword copy_node(const halfword p)
             accent_chr(r) = s;
             s = copy_node_list(bot_accent_chr(p));
             bot_accent_chr(r) = s;
+            s = copy_node_list(overlay_accent_chr(p));
+            overlay_accent_chr(r) = s;
         } else if (type(p) == radical_noad) {
             s = copy_node(left_delimiter(p));
             left_delimiter(r) = s;
@@ -1055,6 +1057,7 @@ void flush_node(halfword p)
         if (type(p) == accent_noad) {
             flush_node_list(accent_chr(p));
             flush_node_list(bot_accent_chr(p));
+            flush_node_list(overlay_accent_chr(p));
         } else if (type(p) == radical_noad) {
             flush_node(left_delimiter(p));
             flush_node_list(degree(p));
@@ -1297,6 +1300,7 @@ void check_node(halfword p)
         dorangetest(p, supscr(p), var_mem_max);
         dorangetest(p, accent_chr(p), var_mem_max);
         dorangetest(p, bot_accent_chr(p), var_mem_max);
+        dorangetest(p, overlay_accent_chr(p), var_mem_max);
         break;
     case fence_noad:
         dorangetest(p, delimiter(p), var_mem_max);
