Repository: netty/netty
File: codec-dns/src/main/java/io/netty/handler/codec/dns/DefaultDnsRecordDecoder.java (Java)

Code before:
        // DNS message compression means that domain names may contain "pointers" to other positions in the packet
        // to build a full message. This means the indexes are meaningful and we need the ability to reference the
        // indexes un-obstructed, and thus we cannot use a slice here.
        // See https://www.ietf.org/rfc/rfc1035 [4.1.4. Message compression]
        if (type == DnsRecordType.PTR) {
            return new DefaultDnsPtrRecord(
                    name, dnsClass, timeToLive, decodeName0(in.duplicate().setIndex(offset, offset + length)));
        }
        if (type == DnsRecordType.CNAME || type == DnsRecordType.NS) {
            return new DefaultDnsRawRecord(name, type, dnsClass, timeToLive,
                                           DnsCodecUtil.decompressDomainName(
                                                   in.duplicate().setIndex(offset, offset + length)));
        }
        if (type ==  DnsRecordType.MX) {
            // MX RDATA: 16-bit preference + exchange (domain name, possibly compressed)
            if (length < 3) {
                throw new CorruptedFrameException("MX record RDATA is too short: " + length);
            }
            final int pref = in.getUnsignedShort(offset);
            ByteBuf exchange = null;
            try {
                exchange = DnsCodecUtil.decompressDomainName(
                        in.duplicate().setIndex(offset + 2, offset + length));

                // Build decompressed RDATA = [preference][expanded exchange name]
                final ByteBuf out = Unpooled.buffer(2 + exchange.readableBytes());
                out.writeShort(pref);
                out.writeBytes(exchange);

                return new DefaultDnsRawRecord(name, type, dnsClass, timeToLive, out);
            } finally {
                if (exchange != null) {
                    exchange.release();
                }
            }
        }

        return new DefaultDnsRawRecord(
                name, type, dnsClass, timeToLive, in.retainedDuplicate().setIndex(offset, offset + length));
    }

    /**
     * Retrieves a domain name given a buffer containing a DNS packet. If the
     * name contains a pointer, the position of the buffer will be set to
     * directly after the pointer's index after the name has been read.
     *
     * @param in the byte buffer containing the DNS packet
     * @return the domain name for an entry
     */
    protected String decodeName0(ByteBuf in) {
        return decodeName(in);

Review comment (suggestion):
```suggestion
                final ByteBuf out = in.alloc().buffer(2 + exchange.readableBytes());
```

Code after:
        // DNS message compression means that domain names may contain "pointers" to other positions in the packet
        // to build a full message. This means the indexes are meaningful and we need the ability to reference the
        // indexes un-obstructed, and thus we cannot use a slice here.
        // See https://www.ietf.org/rfc/rfc1035 [4.1.4. Message compression]
        if (type == DnsRecordType.PTR) {
            return new DefaultDnsPtrRecord(
                    name, dnsClass, timeToLive, decodeName0(in.duplicate().setIndex(offset, offset + length)));
        }
        if (type == DnsRecordType.CNAME || type == DnsRecordType.NS) {
            return new DefaultDnsRawRecord(name, type, dnsClass, timeToLive,
                                           DnsCodecUtil.decompressDomainName(
                                                   in.duplicate().setIndex(offset, offset + length)));
        }
        if (type ==  DnsRecordType.MX) {
            // MX RDATA: 16-bit preference + exchange (domain name, possibly compressed)
            if (length < 3) {
                throw new CorruptedFrameException("MX record RDATA is too short: " + length);
            }
            final int pref = in.getUnsignedShort(offset);
            ByteBuf exchange = null;
            try {
                exchange = DnsCodecUtil.decompressDomainName(
                        in.duplicate().setIndex(offset + 2, offset + length));

                // Build decompressed RDATA = [preference][expanded exchange name]
                final ByteBuf out = in.alloc().buffer(2 + exchange.readableBytes());
                out.writeShort(pref);
                out.writeBytes(exchange);

                return new DefaultDnsRawRecord(name, type, dnsClass, timeToLive, out);
            } finally {
                if (exchange != null) {
                    exchange.release();
                }
            }
        }

        return new DefaultDnsRawRecord(
                name, type, dnsClass, timeToLive, in.retainedDuplicate().setIndex(offset, offset + length));
    }

    /**
     * Retrieves a domain name given a buffer containing a DNS packet. If the
     * name contains a pointer, the position of the buffer will be set to
     * directly after the pointer's index after the name has been read.
     *
     * @param in the byte buffer containing the DNS packet
     * @return the domain name for an entry
     */
    protected String decodeName0(ByteBuf in) {
        return decodeName(in);