From f4e9b9abcff01ac282f7c4df6d0e448cd452ed69 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Mon, 15 Mar 2021 23:19:58 +0900 Subject: [PATCH] Fix a bug in InetAddressUtils, and add a test. InetAddressUtils's parcelInetAddress and #unparcelInetAddress methods do not correctly parcel scoped IPv6 addresses. Fix this by using the same code that LinkProperties uses, and add a test. Bug: 182785371 Test: atest NetworkStaticLibTests Change-Id: Idc9fcbcf4b2b0746c19831fef68b0ddc206eb161 --- .../net/module/util/InetAddressUtils.java | 17 +++++ .../net/module/util/InetAddressUtilsTest.java | 70 +++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 staticlibs/tests/unit/src/com/android/net/module/util/InetAddressUtilsTest.java diff --git a/staticlibs/framework/com/android/net/module/util/InetAddressUtils.java b/staticlibs/framework/com/android/net/module/util/InetAddressUtils.java index 6300328e8d..31d0729709 100644 --- a/staticlibs/framework/com/android/net/module/util/InetAddressUtils.java +++ b/staticlibs/framework/com/android/net/module/util/InetAddressUtils.java @@ -18,6 +18,7 @@ package com.android.net.module.util; import android.os.Parcel; +import java.net.Inet6Address; import java.net.InetAddress; import java.net.UnknownHostException; @@ -27,6 +28,8 @@ import java.net.UnknownHostException; */ public class InetAddressUtils { + private static final int INET6_ADDR_LENGTH = 16; + /** * Writes an InetAddress to a parcel. The address may be null. This is likely faster than * calling writeSerializable. @@ -35,6 +38,13 @@ public class InetAddressUtils { public static void parcelInetAddress(Parcel parcel, InetAddress address, int flags) { byte[] addressArray = (address != null) ? address.getAddress() : null; parcel.writeByteArray(addressArray); + if (address instanceof Inet6Address) { + final Inet6Address v6Address = (Inet6Address) address; + final boolean hasScopeId = v6Address.getScopeId() != 0; + parcel.writeBoolean(hasScopeId); + if (hasScopeId) parcel.writeInt(v6Address.getScopeId()); + } + } /** @@ -47,7 +57,14 @@ public class InetAddressUtils { if (addressArray == null) { return null; } + try { + if (addressArray.length == INET6_ADDR_LENGTH) { + final boolean hasScopeId = in.readBoolean(); + final int scopeId = hasScopeId ? in.readInt() : 0; + return Inet6Address.getByAddress(null /* host */, addressArray, scopeId); + } + return InetAddress.getByAddress(addressArray); } catch (UnknownHostException e) { return null; diff --git a/staticlibs/tests/unit/src/com/android/net/module/util/InetAddressUtilsTest.java b/staticlibs/tests/unit/src/com/android/net/module/util/InetAddressUtilsTest.java new file mode 100644 index 0000000000..2736c53ce8 --- /dev/null +++ b/staticlibs/tests/unit/src/com/android/net/module/util/InetAddressUtilsTest.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.net.module.util; + +import static junit.framework.Assert.assertEquals; + +import android.os.Parcel; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.net.Inet6Address; +import java.net.InetAddress; + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class InetAddressUtilsTest { + + private InetAddress parcelUnparcelAddress(InetAddress addr) { + Parcel p = Parcel.obtain(); + InetAddressUtils.parcelInetAddress(p, addr, 0 /* flags */); + p.setDataPosition(0); + byte[] marshalled = p.marshall(); + p.recycle(); + p = Parcel.obtain(); + p.unmarshall(marshalled, 0, marshalled.length); + p.setDataPosition(0); + InetAddress out = InetAddressUtils.unparcelInetAddress(p); + p.recycle(); + return out; + } + + @Test + public void testParcelUnparcelIpv4Address() throws Exception { + InetAddress ipv4 = InetAddress.getByName("192.0.2.1"); + assertEquals(ipv4, parcelUnparcelAddress(ipv4)); + } + + @Test + public void testParcelUnparcelIpv6Address() throws Exception { + InetAddress ipv6 = InetAddress.getByName("2001:db8::1"); + assertEquals(ipv6, parcelUnparcelAddress(ipv6)); + } + + @Test + public void testParcelUnparcelScopedIpv6Address() throws Exception { + InetAddress ipv6 = InetAddress.getByName("fe80::1%42"); + assertEquals(42, ((Inet6Address) ipv6).getScopeId()); + Inet6Address out = (Inet6Address) parcelUnparcelAddress(ipv6); + assertEquals(ipv6, out); + assertEquals(42, out.getScopeId()); + } +}