Skip to content

Commit

Permalink
Add workaround for ArchLinux + native-image CRC32 miscalculation issue
Browse files Browse the repository at this point in the history
  • Loading branch information
alexarchambault committed Apr 8, 2022
1 parent 95cec0a commit 31d65ad
Show file tree
Hide file tree
Showing 12 changed files with 1,221 additions and 32 deletions.
1 change: 1 addition & 0 deletions build.sc
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,7 @@ trait CliIntegrationBase extends SbtModule with ScalaCliPublishModule with HasTe
| def mostlyStaticDockerfile = "${mostlyStaticDockerfile.toString.replace("\\", "\\\\")}"
| def cs = "${settings.cs().replace("\\", "\\\\")}"
| def workspaceDirName = "$workspaceDirName"
| def dockerArchLinuxImage = "${TestDeps.archLinuxImage}"
|}
|""".stripMargin
if (!os.isFile(dest) || os.read(dest) != code)
Expand Down
159 changes: 159 additions & 0 deletions modules/build/src/main/java/scala/build/internal/zip/ZipCoder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
/*
* Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

package scala.build.internal.zip;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.CodingErrorAction;

import static java.nio.charset.StandardCharsets.UTF_8;

/**
* Utility class for zipfile name and comment decoding and encoding
*/

class ZipCoder {

static final class UTF8 extends ZipCoder {

UTF8(Charset utf8) {
super(utf8);
}

@Override
boolean isUTF8() {
return true;
}

@Override
String toString(byte[] ba, int off, int length) {
try {
return new String(ba, off, length, "UTF-8");
} catch (UnsupportedEncodingException ex) {
throw new RuntimeException(ex);
}
}

@Override
byte[] getBytes(String s) {
try {
return s.getBytes("UTF-8");
} catch (UnsupportedEncodingException ex) {
throw new RuntimeException(ex);
}
}
}

// UTF_8.ArrayEn/Decoder is stateless, so make it singleton.
private static ZipCoder utf8 = new UTF8(UTF_8);

public static ZipCoder get(Charset charset) {
if (charset == UTF_8)
return utf8;
return new ZipCoder(charset);
}

String toString(byte[] ba, int off, int length) {
try {
return decoder().decode(ByteBuffer.wrap(ba, off, length)).toString();
} catch (CharacterCodingException x) {
throw new IllegalArgumentException(x);
}
}

String toString(byte[] ba, int length) {
return toString(ba, 0, length);
}

String toString(byte[] ba) {
return toString(ba, 0, ba.length);
}

byte[] getBytes(String s) {
try {
ByteBuffer bb = encoder().encode(CharBuffer.wrap(s));
int pos = bb.position();
int limit = bb.limit();
if (bb.hasArray() && pos == 0 && limit == bb.capacity()) {
return bb.array();
}
byte[] bytes = new byte[bb.limit() - bb.position()];
bb.get(bytes);
return bytes;
} catch (CharacterCodingException x) {
throw new IllegalArgumentException(x);
}
}

// assume invoked only if "this" is not utf8
byte[] getBytesUTF8(String s) {
return utf8.getBytes(s);
}

static String toStringUTF8(byte[] ba, int len) {
return utf8.toString(ba, 0, len);
}

static String toStringUTF8(byte[] ba, int off, int len) {
return utf8.toString(ba, off, len);
}

boolean isUTF8() {
return false;
}

private Charset cs;
private CharsetDecoder dec;
private CharsetEncoder enc;

private ZipCoder(Charset cs) {
this.cs = cs;
}

protected CharsetDecoder decoder() {
if (dec == null) {
dec = cs.newDecoder()
.onMalformedInput(CodingErrorAction.REPORT)
.onUnmappableCharacter(CodingErrorAction.REPORT);
}
return dec;
}

protected CharsetEncoder encoder() {
if (enc == null) {
enc = cs.newEncoder()
.onMalformedInput(CodingErrorAction.REPORT)
.onUnmappableCharacter(CodingErrorAction.REPORT);
}
return enc;
}
}

100 changes: 100 additions & 0 deletions modules/build/src/main/java/scala/build/internal/zip/ZipConstants.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

package scala.build.internal.zip;

/*
* This interface defines the constants that are used by the classes
* which manipulate ZIP files.
*
* @author David Connelly
* @since 1.1
*/
interface ZipConstants {
/*
* Header signatures
*/
static long LOCSIG = 0x04034b50L; // "PK\003\004"
static long EXTSIG = 0x08074b50L; // "PK\007\008"
static long CENSIG = 0x02014b50L; // "PK\001\002"
static long ENDSIG = 0x06054b50L; // "PK\005\006"

/*
* Header sizes in bytes (including signatures)
*/
static final int LOCHDR = 30; // LOC header size
static final int EXTHDR = 16; // EXT header size
static final int CENHDR = 46; // CEN header size
static final int ENDHDR = 22; // END header size

/*
* Local file (LOC) header field offsets
*/
static final int LOCVER = 4; // version needed to extract
static final int LOCFLG = 6; // general purpose bit flag
static final int LOCHOW = 8; // compression method
static final int LOCTIM = 10; // modification time
static final int LOCCRC = 14; // uncompressed file crc-32 value
static final int LOCSIZ = 18; // compressed size
static final int LOCLEN = 22; // uncompressed size
static final int LOCNAM = 26; // filename length
static final int LOCEXT = 28; // extra field length

/*
* Extra local (EXT) header field offsets
*/
static final int EXTCRC = 4; // uncompressed file crc-32 value
static final int EXTSIZ = 8; // compressed size
static final int EXTLEN = 12; // uncompressed size

/*
* Central directory (CEN) header field offsets
*/
static final int CENVEM = 4; // version made by
static final int CENVER = 6; // version needed to extract
static final int CENFLG = 8; // encrypt, decrypt flags
static final int CENHOW = 10; // compression method
static final int CENTIM = 12; // modification time
static final int CENCRC = 16; // uncompressed file crc-32 value
static final int CENSIZ = 20; // compressed size
static final int CENLEN = 24; // uncompressed size
static final int CENNAM = 28; // filename length
static final int CENEXT = 30; // extra field length
static final int CENCOM = 32; // comment length
static final int CENDSK = 34; // disk number start
static final int CENATT = 36; // internal file attributes
static final int CENATX = 38; // external file attributes
static final int CENOFF = 42; // LOC header offset

/*
* End of central directory (END) header field offsets
*/
static final int ENDSUB = 8; // number of entries on this disk
static final int ENDTOT = 10; // total number of entries
static final int ENDSIZ = 12; // central directory size in bytes
static final int ENDOFF = 16; // offset of first CEN header
static final int ENDCOM = 20; // zip file comment length
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

package scala.build.internal.zip;

/*
* This class defines the constants that are used by the classes
* which manipulate Zip64 files.
*/

class ZipConstants64 {

/*
* ZIP64 constants
*/
static final long ZIP64_ENDSIG = 0x06064b50L; // "PK\006\006"
static final long ZIP64_LOCSIG = 0x07064b50L; // "PK\006\007"
static final int ZIP64_ENDHDR = 56; // ZIP64 end header size
static final int ZIP64_LOCHDR = 20; // ZIP64 end loc header size
static final int ZIP64_EXTHDR = 24; // EXT header size
static final int ZIP64_EXTID = 0x0001; // Extra field Zip64 header ID

static final int ZIP64_MAGICCOUNT = 0xFFFF;
static final long ZIP64_MAGICVAL = 0xFFFFFFFFL;

/*
* Zip64 End of central directory (END) header field offsets
*/
static final int ZIP64_ENDLEN = 4; // size of zip64 end of central dir
static final int ZIP64_ENDVEM = 12; // version made by
static final int ZIP64_ENDVER = 14; // version needed to extract
static final int ZIP64_ENDNMD = 16; // number of this disk
static final int ZIP64_ENDDSK = 20; // disk number of start
static final int ZIP64_ENDTOD = 24; // total number of entries on this disk
static final int ZIP64_ENDTOT = 32; // total number of entries
static final int ZIP64_ENDSIZ = 40; // central directory size in bytes
static final int ZIP64_ENDOFF = 48; // offset of first CEN header
static final int ZIP64_ENDEXT = 56; // zip64 extensible data sector

/*
* Zip64 End of central directory locator field offsets
*/
static final int ZIP64_LOCDSK = 4; // disk number start
static final int ZIP64_LOCOFF = 8; // offset of zip64 end
static final int ZIP64_LOCTOT = 16; // total number of disks

/*
* Zip64 Extra local (EXT) header field offsets
*/
static final int ZIP64_EXTCRC = 4; // uncompressed file crc-32 value
static final int ZIP64_EXTSIZ = 8; // compressed size, 8-byte
static final int ZIP64_EXTLEN = 16; // uncompressed size, 8-byte

/*
* Language encoding flag (general purpose flag bit 11)
*
* If this bit is set the filename and comment fields for this
* entry must be encoded using UTF-8.
*/
static final int USE_UTF8 = 0x800;

/*
* Constants below are defined here (instead of in ZipConstants)
* to avoid being exposed as public fields of ZipFile, ZipEntry,
* ZipInputStream and ZipOutputstream.
*/

/*
* Extra field header ID
*/
static final int EXTID_ZIP64 = 0x0001; // Zip64
static final int EXTID_NTFS = 0x000a; // NTFS
static final int EXTID_UNIX = 0x000d; // UNIX
static final int EXTID_EXTT = 0x5455; // Info-ZIP Extended Timestamp

/*
* EXTT timestamp flags
*/
static final int EXTT_FLAG_LMT = 0x1; // LastModifiedTime
static final int EXTT_FLAG_LAT = 0x2; // LastAccessTime
static final int EXTT_FLAT_CT = 0x4; // CreationTime

private ZipConstants64() {}
}

Loading

0 comments on commit 31d65ad

Please sign in to comment.