Hi,

this diff is somewhat big since I decided to rewrite wrterror() to be
able to get better error messages.

Please review and test this with malloc option C (and other flags). An
example run:

a.out(85360) in free(): chunk canary corrupted 0x13c68f696000 0x18a92@0x18a88

This means I overwrote a byte at offset 0x18a92 in a chunk of size
0x18a88 that is located at 0x13c68f696000.

Only max 32 bytes after the requested size are filled with 0xdb and
checked on free. 

        -Otto

Index: malloc.c
===================================================================
RCS file: /cvs/src/lib/libc/stdlib/malloc.c,v
retrieving revision 1.202
diff -u -p -r1.202 malloc.c
--- malloc.c    15 Oct 2016 18:24:40 -0000      1.202
+++ malloc.c    16 Oct 2016 11:07:45 -0000
@@ -31,6 +31,7 @@
 #include <sys/mman.h>
 #include <sys/uio.h>
 #include <errno.h>
+#include <stdarg.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
@@ -199,6 +200,8 @@ static union {
 char           *malloc_options;        /* compile-time options */
 
 static u_char getrbyte(struct dir_info *d);
+static __dead void wrterror(struct dir_info *d, char *msg, ...)
+    __attribute__((__format__ (printf, 2, 3)));
 
 #ifdef MALLOC_STATS
 void malloc_dump(int, struct dir_info *);
@@ -261,40 +264,26 @@ struct dir_info *getpool(void) 
 }
 
 static __dead void
-wrterror(struct dir_info *d, char *msg, void *p)
+wrterror(struct dir_info *d, char *msg, ...)
 {
-       char            *q = " error: ";
-       struct iovec    iov[7];
-       char            pidbuf[20];
-       char            buf[20];
-       int             saved_errno = errno, i;
-
-       iov[0].iov_base = __progname;
-       iov[0].iov_len = strlen(__progname);
-       iov[1].iov_base = pidbuf;
-       snprintf(pidbuf, sizeof(pidbuf), "(%d) in ", getpid());
-       iov[1].iov_len = strlen(pidbuf);
-       if (d != NULL) {
-               iov[2].iov_base = d->func;
-               iov[2].iov_len = strlen(d->func);
-       } else {
-               iov[2].iov_base = "unknown";
-               iov[2].iov_len = 7;
-       }
-       iov[3].iov_base = q;
-       iov[3].iov_len = strlen(q);
-       iov[4].iov_base = msg;
-       iov[4].iov_len = strlen(msg);
-       iov[5].iov_base = buf;
-       if (p == NULL)
-               iov[5].iov_len = 0;
-       else {
-               snprintf(buf, sizeof(buf), " %010p", p);
-               iov[5].iov_len = strlen(buf);
-       }
-       iov[6].iov_base = "\n";
-       iov[6].iov_len = 1;
-       writev(STDERR_FILENO, iov, 7);
+       struct iovec    iov[3];
+       char            pidbuf[80];
+       char            buf[80];
+       int             saved_errno = errno;
+       va_list         ap;
+
+       iov[0].iov_base = pidbuf;
+       snprintf(pidbuf, sizeof(pidbuf), "%s(%d) in %s(): ", __progname,
+           getpid(), d->func ? d->func : "unknown");
+       iov[0].iov_len = strlen(pidbuf);
+       iov[1].iov_base = buf;
+       va_start(ap, msg);
+       vsnprintf(buf, sizeof(buf), msg, ap);
+       va_end(ap);
+       iov[1].iov_len = strlen(buf);
+       iov[2].iov_base = "\n";
+       iov[2].iov_len = 1;
+       writev(STDERR_FILENO, iov, 3);
 
 #ifdef MALLOC_STATS
        if (mopts.malloc_stats)
@@ -342,12 +331,12 @@ unmap(struct dir_info *d, void *p, size_
        u_int i, offset;
 
        if (sz != PAGEROUND(sz))
-               wrterror(d, "munmap round", NULL);
+               wrterror(d, "munmap round");
 
        if (psz > mopts.malloc_cache) {
                i = munmap(p, sz);
                if (i)
-                       wrterror(d, "munmap", p);
+                       wrterror(d, "munmap %p", p);
                STATS_SUB(d->malloc_used, sz);
                return;
        }
@@ -361,7 +350,7 @@ unmap(struct dir_info *d, void *p, size_
                if (r->p != NULL) {
                        rsz = r->size << MALLOC_PAGESHIFT;
                        if (munmap(r->p, rsz))
-                               wrterror(d, "munmap", r->p);
+                               wrterror(d, "munmap %p", r->p);
                        r->p = NULL;
                        if (tounmap > r->size)
                                tounmap -= r->size;
@@ -373,7 +362,7 @@ unmap(struct dir_info *d, void *p, size_
                }
        }
        if (tounmap > 0)
-               wrterror(d, "malloc cache underflow", NULL);
+               wrterror(d, "malloc cache underflow");
        for (i = 0; i < mopts.malloc_cache; i++) {
                r = &d->free_regions[(i + offset) & (mopts.malloc_cache - 1)];
                if (r->p == NULL) {
@@ -393,9 +382,9 @@ unmap(struct dir_info *d, void *p, size_
                }
        }
        if (i == mopts.malloc_cache)
-               wrterror(d, "malloc free slot lost", NULL);
+               wrterror(d, "malloc free slot lost");
        if (d->free_regions_size > mopts.malloc_cache)
-               wrterror(d, "malloc cache overflow", NULL);
+               wrterror(d, "malloc cache overflow");
 }
 
 static void
@@ -410,7 +399,7 @@ zapcacheregion(struct dir_info *d, void 
                if (r->p >= p && r->p <= (void *)((char *)p + len)) {
                        rsz = r->size << MALLOC_PAGESHIFT;
                        if (munmap(r->p, rsz))
-                               wrterror(d, "munmap", r->p);
+                               wrterror(d, "munmap %p", r->p);
                        r->p = NULL;
                        d->free_regions_size -= r->size;
                        r->size = 0;
@@ -429,9 +418,9 @@ map(struct dir_info *d, void *hint, size
 
        if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) ||
            d->canary1 != ~d->canary2)
-               wrterror(d, "internal struct corrupt", NULL);
+               wrterror(d, "internal struct corrupt");
        if (sz != PAGEROUND(sz))
-               wrterror(d, "map round", NULL);
+               wrterror(d, "map round");
 
        if (!hint && psz > d->free_regions_size) {
                _MALLOC_LEAVE(d);
@@ -486,7 +475,7 @@ map(struct dir_info *d, void *hint, size
        if (hint)
                return MAP_FAILED;
        if (d->free_regions_size > mopts.malloc_cache)
-               wrterror(d, "malloc cache", NULL);
+               wrterror(d, "malloc cache");
        _MALLOC_LEAVE(d);
        p = MMAP(sz);
        _MALLOC_ENTER(d);
@@ -673,7 +662,7 @@ omalloc_poolinit(struct dir_info **dp)
         * lies (subject to alignment by 1 << MALLOC_MINSHIFT)
         */
        if ((p = MMAP(DIR_INFO_RSZ + (MALLOC_PAGESIZE * 2))) == MAP_FAILED)
-               wrterror(NULL, "malloc init mmap failed", NULL);
+               wrterror(NULL, "malloc init mmap failed");
        mprotect(p, MALLOC_PAGESIZE, PROT_NONE);
        mprotect(p + MALLOC_PAGESIZE + DIR_INFO_RSZ,
            MALLOC_PAGESIZE, PROT_NONE);
@@ -687,7 +676,7 @@ omalloc_poolinit(struct dir_info **dp)
        d->r = MMAP(regioninfo_size);
        if (d->r == MAP_FAILED) {
                d->regions_total = 0;
-               wrterror(NULL, "malloc init mmap failed", NULL);
+               wrterror(NULL, "malloc init mmap failed");
        }
        for (i = 0; i <= MALLOC_MAXSHIFT; i++) {
                LIST_INIT(&d->chunk_info_list[i]);
@@ -738,7 +727,7 @@ omalloc_grow(struct dir_info *d)
        }
        /* avoid pages containing meta info to end up in cache */
        if (munmap(d->r, d->regions_total * sizeof(struct region_info)))
-               wrterror(d, "munmap", d->r);
+               wrterror(d, "munmap %p", d->r);
        else
                STATS_SUB(d->malloc_used,
                    d->regions_total * sizeof(struct region_info));
@@ -828,7 +817,7 @@ find(struct dir_info *d, void *p)
 
        if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) ||
            d->canary1 != ~d->canary2)
-               wrterror(d, "internal struct corrupt", NULL);
+               wrterror(d, "internal struct corrupt");
        p = MASK_POINTER(p);
        index = hash(p) & mask;
        r = d->r[index].p;
@@ -851,7 +840,7 @@ delete(struct dir_info *d, struct region
        size_t i, j, r;
 
        if (d->regions_total & (d->regions_total - 1))
-               wrterror(d, "regions_total not 2^x", NULL);
+               wrterror(d, "regions_total not 2^x");
        d->regions_free++;
        STATS_INC(d->deletes);
 
@@ -936,7 +925,7 @@ omalloc_make_chunks(struct dir_info *d, 
 
        bits++;
        if ((uintptr_t)pp & bits)
-               wrterror(d, "pp & bits", pp);
+               wrterror(d, "pp & bits %p", pp);
 
        insert(d, (void *)((uintptr_t)pp | bits), (uintptr_t)bp, NULL);
        return bp;
@@ -956,7 +945,7 @@ malloc_bytes(struct dir_info *d, size_t 
 
        if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) ||
            d->canary1 != ~d->canary2)
-               wrterror(d, "internal struct corrupt", NULL);
+               wrterror(d, "internal struct corrupt");
 
        size = argsize;
 
@@ -984,7 +973,7 @@ malloc_bytes(struct dir_info *d, size_t 
        }
 
        if (bp->canary != d->canary1)
-               wrterror(d, "chunk info corrupted", NULL);
+               wrterror(d, "chunk info corrupted");
 
        i = d->chunk_start;
        if (bp->free > 1)
@@ -1045,6 +1034,25 @@ malloc_bytes(struct dir_info *d, size_t 
        return ((char *)bp->page + k);
 }
 
+static void
+validate_canary(struct dir_info *d, u_char *ptr, size_t sz, size_t allocated)
+{
+       size_t check_sz = allocated - sz;
+       u_char *p, *q;
+
+       if (check_sz > CHUNK_CHECK_LENGTH)
+               check_sz = CHUNK_CHECK_LENGTH;
+       p = (u_char *)ptr + sz;
+       q = p + check_sz;
+
+       while (p < q) {
+               if (*p++ != SOME_JUNK) {
+                       wrterror(d, "chunk canary corrupted %p %#tx@%#zx",
+                           ptr, p - ptr - 1, sz);
+               }
+       }
+}
+
 static uint32_t
 find_chunknum(struct dir_info *d, struct region_info *r, void *ptr, int check)
 {
@@ -1053,32 +1061,20 @@ find_chunknum(struct dir_info *d, struct
 
        info = (struct chunk_info *)r->size;
        if (info->canary != d->canary1)
-               wrterror(d, "chunk info corrupted", NULL);
+               wrterror(d, "chunk info corrupted");
 
        /* Find the chunk number on the page */
        chunknum = ((uintptr_t)ptr & MALLOC_PAGEMASK) >> info->shift;
        if (check && mopts.chunk_canaries && info->size > 0) {
-               size_t sz = info->bits[info->offset + chunknum];
-               size_t check_sz = info->size - sz;
-               u_char *p, *q;
-
-               if (check_sz > CHUNK_CHECK_LENGTH)
-                       check_sz = CHUNK_CHECK_LENGTH;
-               p = (u_char *)ptr + sz;
-               q = p + check_sz;
-
-               while (p < q)
-                       if (*p++ != SOME_JUNK) {
-                               q = (void *)(sz << 16 | p - (u_char *)ptr - 1);
-                               wrterror(d, "chunk canary corrupted: ", q);
-                       }
+               validate_canary(d, ptr, info->bits[info->offset + chunknum],
+                   info->size);
        }
 
        if ((uintptr_t)ptr & ((1U << (info->shift)) - 1))
-               wrterror(d, "modified chunk-pointer", ptr);
+               wrterror(d, "modified chunk-pointer %p", ptr);
        if (info->bits[chunknum / MALLOC_BITS] &
            (1U << (chunknum % MALLOC_BITS)))
-               wrterror(d, "chunk is already free", ptr);
+               wrterror(d, "chunk is already free %p", ptr);
        return chunknum;
 }
 
@@ -1156,7 +1152,7 @@ omalloc(struct dir_info *pool, size_t sz
                if (mopts.malloc_guard) {
                        if (mprotect((char *)p + psz - mopts.malloc_guard,
                            mopts.malloc_guard, PROT_NONE))
-                               wrterror(pool, "mprotect", NULL);
+                               wrterror(pool, "mprotect");
                        STATS_ADD(pool->malloc_guarded, mopts.malloc_guard);
                }
 
@@ -1181,6 +1177,13 @@ omalloc(struct dir_info *pool, size_t sz
                                        memset(p, SOME_JUNK,
                                            psz - mopts.malloc_guard);
                        }
+                       else if (mopts.chunk_canaries) {
+                               size_t csz = psz - mopts.malloc_guard - sz;
+
+                               if (csz > CHUNK_CHECK_LENGTH)
+                                       csz = CHUNK_CHECK_LENGTH;
+                               memset(p + sz, SOME_JUNK, csz);
+                       }
                }
 
        } else {
@@ -1205,7 +1208,7 @@ malloc_recurse(struct dir_info *d)
 
        if (noprint == 0) {
                noprint = 1;
-               wrterror(d, "recursive call", NULL);
+               wrterror(d, "recursive call");
        }
        d->active--;
        _MALLOC_UNLOCK(d->mutex);
@@ -1264,7 +1267,7 @@ malloc(size_t size)
                d = getpool();
        }
        _MALLOC_LOCK(d->mutex);
-       d->func = "malloc():";
+       d->func = "malloc";
        
        if (d->active++) {
                malloc_recurse(d);
@@ -1274,7 +1277,7 @@ malloc(size_t size)
        d->active--;
        _MALLOC_UNLOCK(d->mutex);
        if (r == NULL && mopts.malloc_xmalloc)
-               wrterror(d, "out of memory", NULL);
+               wrterror(d, "out of memory");
        if (r != NULL)
                errno = saved_errno;
        return r;
@@ -1291,13 +1294,13 @@ validate_junk(struct dir_info *pool, voi
                return;
        r = find(pool, p);
        if (r == NULL)
-               wrterror(pool, "bogus pointer in validate_junk", p);
+               wrterror(pool, "bogus pointer in validate_junk %p", p);
        REALSIZE(sz, r);
        if (sz > CHUNK_CHECK_LENGTH)
                sz = CHUNK_CHECK_LENGTH;
        for (byte = 0; byte < sz; byte++) {
                if (((unsigned char *)p)[byte] != SOME_FREEJUNK)
-                       wrterror(pool, "use after free", p);
+                       wrterror(pool, "use after free %p", p);
        }
 }
 
@@ -1327,7 +1330,7 @@ ofree(struct dir_info *argpool, void *p)
                        }
                }       
                if (r == NULL)
-                       wrterror(pool, "bogus pointer (double free?)", p);
+                       wrterror(pool, "bogus pointer (double free?) %p", p);
        }
 
        REALSIZE(sz, r);
@@ -1335,7 +1338,11 @@ ofree(struct dir_info *argpool, void *p)
                if (sz - mopts.malloc_guard >= MALLOC_PAGESIZE -
                    MALLOC_LEEWAY) {
                        if (r->p != p)
-                               wrterror(pool, "bogus pointer", p);
+                               wrterror(pool, "bogus pointer %p", p);
+                       if (mopts.chunk_canaries)
+                               validate_canary(pool, p,
+                                   sz - mopts.malloc_guard,
+                                   PAGEROUND(sz - mopts.malloc_guard));
                } else {
 #if notyetbecause_of_realloc
                        /* shifted towards the end */
@@ -1348,12 +1355,12 @@ ofree(struct dir_info *argpool, void *p)
                }
                if (mopts.malloc_guard) {
                        if (sz < mopts.malloc_guard)
-                               wrterror(pool, "guard size", NULL);
+                               wrterror(pool, "guard size");
                        if (!mopts.malloc_freeunmap) {
                                if (mprotect((char *)p + PAGEROUND(sz) -
                                    mopts.malloc_guard, mopts.malloc_guard,
                                    PROT_READ | PROT_WRITE))
-                                       wrterror(pool, "mprotect", NULL);
+                                       wrterror(pool, "mprotect");
                        }
                        STATS_SUB(pool->malloc_guarded, mopts.malloc_guard);
                }
@@ -1371,7 +1378,7 @@ ofree(struct dir_info *argpool, void *p)
                        tmp = p;
                        p = pool->delayed_chunks[i];
                        if (tmp == p)
-                               wrterror(pool, "double free", p);
+                               wrterror(pool, "double free %p", tmp);
                        if (mopts.malloc_junk)
                                validate_junk(pool, p);
                        pool->delayed_chunks[i] = tmp;
@@ -1382,11 +1389,12 @@ ofree(struct dir_info *argpool, void *p)
                if (p != NULL) {
                        r = find(pool, p);
                        if (r == NULL)
-                               wrterror(pool, "bogus pointer (double free?)", 
p);
+                               wrterror(pool,
+                                   "bogus pointer (double free?) %p", p);
                        free_bytes(pool, r, p);
                }
        }
-done:
+
        if (argpool != pool) {
                pool->active--;
                _MALLOC_UNLOCK(pool->mutex);
@@ -1407,9 +1415,9 @@ free(void *ptr)
 
        d = getpool();
        if (d == NULL)
-               wrterror(d, "free() called before allocation", NULL);
+               wrterror(d, "free() called before allocation");
        _MALLOC_LOCK(d->mutex);
-       d->func = "free():";
+       d->func = "free";
        if (d->active++) {
                malloc_recurse(d);
                return;
@@ -1453,7 +1461,7 @@ orealloc(struct dir_info *argpool, void 
                        }
                }       
                if (r == NULL)
-                       wrterror(pool, "bogus pointer (double free?)", p);
+                       wrterror(pool, "bogus pointer (double free?) %p", p);
        }
        if (newsz >= SIZE_MAX - mopts.malloc_guard - MALLOC_PAGESIZE) {
                errno = ENOMEM;
@@ -1465,7 +1473,7 @@ orealloc(struct dir_info *argpool, void 
        goldsz = oldsz;
        if (oldsz > MALLOC_MAXCHUNK) {
                if (oldsz < mopts.malloc_guard)
-                       wrterror(pool, "guard size", NULL);
+                       wrterror(pool, "guard size");
                oldsz -= mopts.malloc_guard;
        }
 
@@ -1474,7 +1482,7 @@ orealloc(struct dir_info *argpool, void 
                gnewsz += mopts.malloc_guard;
 
        if (newsz > MALLOC_MAXCHUNK && oldsz > MALLOC_MAXCHUNK && p == r->p &&
-           !mopts.malloc_realloc) {
+           !mopts.chunk_canaries && !mopts.malloc_realloc) {
                size_t roldsz = PAGEROUND(goldsz);
                size_t rnewsz = PAGEROUND(gnewsz);
 
@@ -1505,7 +1513,7 @@ gotit:
                                        goto done;
                                } else if (q != MAP_FAILED) {
                                        if (munmap(q, needed))
-                                               wrterror(pool, "munmap", q);
+                                               wrterror(pool, "munmap %p", q);
                                }
                        }
                } else if (rnewsz < roldsz) {
@@ -1513,11 +1521,11 @@ gotit:
                                if (mprotect((char *)p + roldsz -
                                    mopts.malloc_guard, mopts.malloc_guard,
                                    PROT_READ | PROT_WRITE))
-                                       wrterror(pool, "mprotect", NULL);
+                                       wrterror(pool, "mprotect");
                                if (mprotect((char *)p + rnewsz -
                                    mopts.malloc_guard, mopts.malloc_guard,
                                    PROT_NONE))
-                                       wrterror(pool, "mprotect", NULL);
+                                       wrterror(pool, "mprotect");
                        }
                        unmap(pool, (char *)p + rnewsz, roldsz - rnewsz);
                        r->size = gnewsz;
@@ -1578,7 +1586,7 @@ realloc(void *ptr, size_t size)
                d = getpool();
        }
        _MALLOC_LOCK(d->mutex);
-       d->func = "realloc():";
+       d->func = "realloc";
        if (d->active++) {
                malloc_recurse(d);
                return NULL;
@@ -1588,7 +1596,7 @@ realloc(void *ptr, size_t size)
        d->active--;
        _MALLOC_UNLOCK(d->mutex);
        if (r == NULL && mopts.malloc_xmalloc)
-               wrterror(d, "out of memory", NULL);
+               wrterror(d, "out of memory");
        if (r != NULL)
                errno = saved_errno;
        return r;
@@ -1615,12 +1623,12 @@ calloc(size_t nmemb, size_t size)
                d = getpool();
        }
        _MALLOC_LOCK(d->mutex);
-       d->func = "calloc():";
+       d->func = "calloc";
        if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
            nmemb > 0 && SIZE_MAX / nmemb < size) {
                _MALLOC_UNLOCK(d->mutex);
                if (mopts.malloc_xmalloc)
-                       wrterror(d, "out of memory", NULL);
+                       wrterror(d, "out of memory");
                errno = ENOMEM;
                return NULL;
        }
@@ -1636,7 +1644,7 @@ calloc(size_t nmemb, size_t size)
        d->active--;
        _MALLOC_UNLOCK(d->mutex);
        if (r == NULL && mopts.malloc_xmalloc)
-               wrterror(d, "out of memory", NULL);
+               wrterror(d, "out of memory");
        if (r != NULL)
                errno = saved_errno;
        return r;
@@ -1649,9 +1657,9 @@ mapalign(struct dir_info *d, size_t alig
        char *p, *q;
 
        if (alignment < MALLOC_PAGESIZE || ((alignment - 1) & alignment) != 0)
-               wrterror(d, "mapalign bad alignment", NULL);
+               wrterror(d, "mapalign bad alignment");
        if (sz != PAGEROUND(sz))
-               wrterror(d, "mapalign round", NULL);
+               wrterror(d, "mapalign round");
 
        /* Allocate sz + alignment bytes of memory, which must include a
         * subrange of size bytes that is properly aligned.  Unmap the
@@ -1668,10 +1676,10 @@ mapalign(struct dir_info *d, size_t alig
        q = (char *)(((uintptr_t)p + alignment - 1) & ~(alignment - 1));
        if (q != p) {
                if (munmap(p, q - p))
-                       wrterror(d, "munmap", p);
+                       wrterror(d, "munmap %p", p);
        }
        if (munmap(q + sz, alignment - (q - p)))
-               wrterror(d, "munmap", q + sz);
+               wrterror(d, "munmap %p", q + sz);
        STATS_SUB(d->malloc_used, alignment);
 
        return q;
@@ -1716,7 +1724,7 @@ omemalign(struct dir_info *pool, size_t 
        if (mopts.malloc_guard) {
                if (mprotect((char *)p + psz - mopts.malloc_guard,
                    mopts.malloc_guard, PROT_NONE))
-                       wrterror(pool, "mprotect", NULL);
+                       wrterror(pool, "mprotect");
                STATS_ADD(pool->malloc_guarded, mopts.malloc_guard);
        }
 
@@ -1748,7 +1756,7 @@ posix_memalign(void **memptr, size_t ali
                d = getpool();
        }
        _MALLOC_LOCK(d->mutex);
-       d->func = "posix_memalign():";
+       d->func = "posix_memalign";
        if (d->active++) {
                malloc_recurse(d);
                goto err;
@@ -1758,7 +1766,7 @@ posix_memalign(void **memptr, size_t ali
        _MALLOC_UNLOCK(d->mutex);
        if (r == NULL) {
                if (mopts.malloc_xmalloc)
-                       wrterror(d, "out of memory", NULL);
+                       wrterror(d, "out of memory");
                goto err;
        }
        errno = saved_errno;
@@ -2007,7 +2015,7 @@ malloc_dump(int fd, struct dir_info *poo
                        continue;
                r = find(pool, p);
                if (r == NULL)
-                       wrterror(pool, "bogus pointer in malloc_dump", p);
+                       wrterror(pool, "bogus pointer in malloc_dump %p", p);
                free_bytes(pool, r, p);
                pool->delayed_chunks[i] = NULL;
        }


Reply via email to