ngx_int_t
ngx_atoi(u_char *line, size_t n)
{
    ngx_int_t  value, cutoff, cutlim;
    if (n == 0) {
        return NGX_ERROR;
    }
    cutoff = NGX_MAX_INT_T_VALUE / 10;
    cutlim = NGX_MAX_INT_T_VALUE % 10;
    for (value = 0; n--; line++) {
        if (*line < '0' || *line > '9') {
            return NGX_ERROR;
        }
        if (value >= cutoff && (value > cutoff || *line - '0' > cutlim)) {
            return NGX_ERROR;
        }
        value = value * 10 + (*line - '0');
    }
    return value;
}
['static void\nngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,\n    ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan)\n{\n    char                 *err;\n    size_t                len;\n    in_addr_t             addr;\n    int32_t               ttl;\n    ngx_int_t             octet;\n    ngx_str_t             name;\n    ngx_uint_t            mask, type, class, qident, a, i, start;\n    ngx_queue_t          *expire_queue;\n    ngx_rbtree_t         *tree;\n    ngx_resolver_an_t    *an;\n    ngx_resolver_ctx_t   *ctx, *next;\n    ngx_resolver_node_t  *rn;\n#if (NGX_HAVE_INET6)\n    uint32_t              hash;\n    ngx_int_t             digit;\n    struct in6_addr       addr6;\n#endif\n    if (ngx_resolver_copy(r, &name, buf,\n                          buf + sizeof(ngx_resolver_hdr_t), buf + n)\n        != NGX_OK)\n    {\n        return;\n    }\n    ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver qs:%V", &name);\n    addr = 0;\n    i = sizeof(ngx_resolver_hdr_t);\n    for (mask = 0; mask < 32; mask += 8) {\n        len = buf[i++];\n        octet = ngx_atoi(&buf[i], len);\n        if (octet == NGX_ERROR || octet > 255) {\n            goto invalid_in_addr_arpa;\n        }\n        addr += octet << mask;\n        i += len;\n    }\n    if (ngx_strcasecmp(&buf[i], (u_char *) "\\7in-addr\\4arpa") == 0) {\n        i += sizeof("\\7in-addr\\4arpa");\n        rn = ngx_resolver_lookup_addr(r, addr);\n        tree = &r->addr_rbtree;\n        expire_queue = &r->addr_expire_queue;\n        goto valid;\n    }\ninvalid_in_addr_arpa:\n#if (NGX_HAVE_INET6)\n    i = sizeof(ngx_resolver_hdr_t);\n    for (octet = 15; octet >= 0; octet--) {\n        if (buf[i++] != \'\\1\') {\n            goto invalid_ip6_arpa;\n        }\n        digit = ngx_hextoi(&buf[i++], 1);\n        if (digit == NGX_ERROR) {\n            goto invalid_ip6_arpa;\n        }\n        addr6.s6_addr[octet] = (u_char) digit;\n        if (buf[i++] != \'\\1\') {\n            goto invalid_ip6_arpa;\n        }\n        digit = ngx_hextoi(&buf[i++], 1);\n        if (digit == NGX_ERROR) {\n            goto invalid_ip6_arpa;\n        }\n        addr6.s6_addr[octet] += (u_char) (digit * 16);\n    }\n    if (ngx_strcasecmp(&buf[i], (u_char *) "\\3ip6\\4arpa") == 0) {\n        i += sizeof("\\3ip6\\4arpa");\n        hash = ngx_crc32_short(addr6.s6_addr, 16);\n        rn = ngx_resolver_lookup_addr6(r, &addr6, hash);\n        tree = &r->addr6_rbtree;\n        expire_queue = &r->addr6_expire_queue;\n        goto valid;\n    }\ninvalid_ip6_arpa:\n#endif\n    ngx_log_error(r->log_level, r->log, 0,\n                  "invalid in-addr.arpa or ip6.arpa name in DNS response");\n    ngx_resolver_free(r, name.data);\n    return;\nvalid:\n    if (rn == NULL || rn->query == NULL) {\n        ngx_log_error(r->log_level, r->log, 0,\n                      "unexpected response for %V", &name);\n        ngx_resolver_free(r, name.data);\n        goto failed;\n    }\n    qident = (rn->query[0] << 8) + rn->query[1];\n    if (ident != qident) {\n        ngx_log_error(r->log_level, r->log, 0,\n                      "wrong ident %ui response for %V, expect %ui",\n                      ident, &name, qident);\n        ngx_resolver_free(r, name.data);\n        goto failed;\n    }\n    ngx_resolver_free(r, name.data);\n    if (code == 0 && nan == 0) {\n        code = NGX_RESOLVE_NXDOMAIN;\n    }\n    if (code) {\n        next = rn->waiting;\n        rn->waiting = NULL;\n        ngx_queue_remove(&rn->queue);\n        ngx_rbtree_delete(tree, &rn->node);\n        while (next) {\n            ctx = next;\n            ctx->state = code;\n            next = ctx->next;\n            ctx->handler(ctx);\n        }\n        ngx_resolver_free_node(r, rn);\n        return;\n    }\n    i += sizeof(ngx_resolver_qs_t);\n    for (a = 0; a < nan; a++) {\n        start = i;\n        while (i < n) {\n            if (buf[i] & 0xc0) {\n                i += 2;\n                goto found;\n            }\n            if (buf[i] == 0) {\n                i++;\n                goto test_length;\n            }\n            i += 1 + buf[i];\n        }\n        goto short_response;\n    test_length:\n        if (i - start < 2) {\n            err = "invalid name in DNS response";\n            goto invalid;\n        }\n    found:\n        if (i + sizeof(ngx_resolver_an_t) >= n) {\n            goto short_response;\n        }\n        an = (ngx_resolver_an_t *) &buf[i];\n        type = (an->type_hi << 8) + an->type_lo;\n        class = (an->class_hi << 8) + an->class_lo;\n        len = (an->len_hi << 8) + an->len_lo;\n        ttl = (an->ttl[0] << 24) + (an->ttl[1] << 16)\n            + (an->ttl[2] << 8) + (an->ttl[3]);\n        if (class != 1) {\n            ngx_log_error(r->log_level, r->log, 0,\n                          "unexpected RR class %ui", class);\n            goto failed;\n        }\n        if (ttl < 0) {\n            ttl = 0;\n        }\n        ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0,\n                      "resolver qt:%ui cl:%ui len:%uz",\n                      type, class, len);\n        i += sizeof(ngx_resolver_an_t);\n        switch (type) {\n        case NGX_RESOLVE_PTR:\n            goto ptr;\n        case NGX_RESOLVE_CNAME:\n            break;\n        default:\n            ngx_log_error(r->log_level, r->log, 0,\n                          "unexpected RR type %ui", type);\n        }\n        i += len;\n    }\n    ngx_log_error(r->log_level, r->log, 0,\n                  "no PTR type in DNS response");\n    return;\nptr:\n    if (ngx_resolver_copy(r, &name, buf, buf + i, buf + n) != NGX_OK) {\n        goto failed;\n    }\n    ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver an:%V", &name);\n    if (name.len != (size_t) rn->nlen\n        || ngx_strncmp(name.data, rn->name, name.len) != 0)\n    {\n        if (rn->nlen) {\n            ngx_resolver_free(r, rn->name);\n        }\n        rn->nlen = (u_short) name.len;\n        rn->name = name.data;\n        name.data = ngx_resolver_dup(r, rn->name, name.len);\n        if (name.data == NULL) {\n            goto failed;\n        }\n    }\n    ngx_queue_remove(&rn->queue);\n    rn->valid = ngx_time() + (r->valid ? r->valid : ttl);\n    rn->expire = ngx_time() + r->expire;\n    ngx_queue_insert_head(expire_queue, &rn->queue);\n    next = rn->waiting;\n    rn->waiting = NULL;\n    while (next) {\n        ctx = next;\n        ctx->state = NGX_OK;\n        ctx->name = name;\n        next = ctx->next;\n        ctx->handler(ctx);\n    }\n    ngx_resolver_free(r, name.data);\n    return;\nshort_response:\n    err = "short DNS response";\ninvalid:\n    ngx_log_error(r->log_level, r->log, 0, err);\n    return;\nfailed:\n    return;\n}', 'static ngx_int_t\nngx_resolver_copy(ngx_resolver_t *r, ngx_str_t *name, u_char *buf, u_char *src,\n    u_char *last)\n{\n    char        *err;\n    u_char      *p, *dst;\n    ssize_t      len;\n    ngx_uint_t   i, n;\n    p = src;\n    len = -1;\n    for (i = 0; i < 128; i++) {\n        n = *p++;\n        if (n == 0) {\n            goto done;\n        }\n        if (n & 0xc0) {\n            n = ((n & 0x3f) << 8) + *p;\n            p = &buf[n];\n        } else {\n            len += 1 + n;\n            p = &p[n];\n        }\n        if (p >= last) {\n            err = "name is out of response";\n            goto invalid;\n        }\n    }\n    err = "compression pointers loop";\ninvalid:\n    ngx_log_error(r->log_level, r->log, 0, err);\n    return NGX_ERROR;\ndone:\n    if (name == NULL) {\n        return NGX_OK;\n    }\n    if (len == -1) {\n        ngx_str_null(name);\n        return NGX_OK;\n    }\n    dst = ngx_resolver_alloc(r, len);\n    if (dst == NULL) {\n        return NGX_ERROR;\n    }\n    name->data = dst;\n    n = *src++;\n    for ( ;; ) {\n        if (n & 0xc0) {\n            n = ((n & 0x3f) << 8) + *src;\n            src = &buf[n];\n            n = *src++;\n        } else {\n            ngx_strlow(dst, src, n);\n            dst += n;\n            src += n;\n            n = *src++;\n            if (n != 0) {\n                *dst++ = \'.\';\n            }\n        }\n        if (n == 0) {\n            name->len = dst - name->data;\n            return NGX_OK;\n        }\n    }\n}', "ngx_int_t\nngx_atoi(u_char *line, size_t n)\n{\n    ngx_int_t  value, cutoff, cutlim;\n    if (n == 0) {\n        return NGX_ERROR;\n    }\n    cutoff = NGX_MAX_INT_T_VALUE / 10;\n    cutlim = NGX_MAX_INT_T_VALUE % 10;\n    for (value = 0; n--; line++) {\n        if (*line < '0' || *line > '9') {\n            return NGX_ERROR;\n        }\n        if (value >= cutoff && (value > cutoff || *line - '0' > cutlim)) {\n            return NGX_ERROR;\n        }\n        value = value * 10 + (*line - '0');\n    }\n    return value;\n}"]