I'm importing some old C code into a swift project, and porting it across to pure swift code.
Some of it does "encryption" wherein it does something like
let a = UInt8(x) // e.g. 30
let b = a - 237
In C this just underflows and wraps around, which is fine for this particular function.
In swift this triggers a fatalError and terminates my program with EXC_BAD_INSTRUCTION because swift by default is designed to catch integer over/underflow.
I'm aware I can turn this checking off at the entire project level by compiling with -Ofast, but I'd really like to just turn off the overflow checking for this one line of code (or perhaps just the specific function itself).
Note: I specifically want to preserve the behaviour of the C function, not just promote things up to Int32 or Int64
This particular term seems really hard to google for.
Update: The answer is the Overflow operators, which are
&- for subtraction
&+ for addition
&* for multiply
I couldn't find them in my previous searching. Oops
You can use addWithOverflow or subtractWithOverflow class method of Int, UInt8 etc types
E.g. let b = UInt8.subtractWithOverflow(a, 237)
Apart from overflow operators (such as &+ , &* etc) you can make use of reporting overflow methods (available for integers) to know whether the arithmetic operation resulted in an overflow or not such as this example :
let int1 : Int8 = Int8.max //127
let int2: Int8 = 50
//this method provides a boolean flag
let (sum1,didOverflow ):(Int8,Bool) = int1.addingReportingOverflow(int2)
print("sum is \(sum1) and isOverflowing = \(didOverflow)")
//sum is -79 and isOverflowing is true
let sum = int1 &+ int2 //wont crash for overflows
let unsafeSum = int1.unsafeAdding(int2) //crashes whenever overflow
Related
Say I have the following code...
let x = "ABCDE"
// 'x' is a String
var y = x[1...3]
// 'y' is a Substring that equals "BCD"
If you only have access to y, is it possible to access x, or specifically parts of x which are outside the range of y? (i.e. can you access 'A' or 'E', or grow the range of y?)
So here's what Apple says:
Important
Don’t store substrings longer than you need them to perform a specific
operation. A substring holds a reference to the entire storage of the
string it comes from, not just to the portion it presents, even when
there is no other reference to the original string. Storing substrings
may, therefore, prolong the lifetime of string data that is no longer
otherwise accessible, which can appear to be memory leakage.
Now I find their use of the word "otherwise" in the last sentence rather interesting. It seems to me to keep the door open on this question - could a substring be manipulated to be expanded to include memory on either side that we know still exists as part of the original string?
So here's what I'd think is a fair test:
let x = "ABCDEFGH"
let substr = x.prefix(3)
var substrIndex = substr.startIndex
substr.formIndex(&substrIndex, offsetBy: 4) // offset beyond the substring
let prefix = substr.prefix(through:substrIndex)
print(prefix)
So what'cha think that would print?
Actually we never get to the print. We get a runtime fatal error instead.
Thread 1: Fatal error: Operation results in an invalid index
BTW, even trying the following results in an EXC_BAD_ACCESS crash:
let x = "ABCDEFGH"
var substr = x.prefix(3)
withUnsafePointer(to: &substr)
{ substrPointer in
let z = substrPointer.advanced(by: 3)
print(z.pointee)
}
So I don't think there's a way to get to the rest of the string if you just have a substring... from within Substring or String classes anyhow, or even dealing with unsafe pointers. I'm sure there's a way using direct memory access, for Apple claims the rest of the String's memory is there... but you'd probably have to fall back to C or C++.
The following code will crash with an EXC_BADINSTRUCTION. Im trying to figure out what is the actual cause of the crash, or if there is a better way of computing a hashValue for a given struct.
struct Provider{
let name = "AmazonPrime"
let country = "us"
let identifier = "us-AmazonPrime"
}
let provider = Provider()
//Crash on hashValue
let hashValue = (provider.name.hashValue + provider.country.hashValue + provider.identifier.hashValue)
The Swift language does not allow for math to overflow when using the basic arithmetic operators (as noted in the Arithmetic Operators area of the Basic Operators section of The Swift Programming Guide). If the 3 hash values you're adding exceed Int.max (Hashable declares the hashValue as an Int), you will receive that crash type.
If you want overflow, you have to use the overflow arithmetic operators, as defined in the Overflow Operators area of the Basic Operators section of the Swift Programming Guide.
They are: &+ &- and &*
I think I get the basic idea behind ASN.1 parsing. Walk the bytes, interpret them and do something useful with them. Alas I am stuck on the implementation.
Apple has no sample code (that I could find), probably for security reasons. OpenSSL is not very well documented, so I can only guess at what the functions actually do. The only sample code in swift I did find doesn't handle case 17 (the in-app purchases), which is the one thing I am interested in.
I tried figuring out where in the data stream the pointer is located, but I always get the same nonsensical result of 49.
let receiptContents = NSData(contentsOfURL: receiptLocation)!
let receiptBIO = BIO_new(BIO_s_mem())
BIO_write(receiptBIO, receiptContents.bytes, Int32(receiptContents.length))
contents = d2i_PKCS7_bio(receiptBIO, nil)
//parsing
var currentIndex = UnsafePointer<UInt8>()
var endIndex = UnsafePointer<UInt8>()
let octets = pkcs7_d_data(pkcs7_d_sign(self.contents).memory.contents)
var ptr = UnsafePointer<UInt8>(octets.memory.data)
let end = ptr.advancedBy(Int(octets.memory.length))
println(ptr.memory) //always 49 ???
println(end.memory) //always 0 ???
println(octets.memory.length)
I tried parsing the NSData myself, but well, what is the type of the binaire data?
receiptContents = NSData(contentsOfURL: receiptLocation)!
//get bytes
let count = receiptContents.length / sizeof(UInt8)
var bytes = [UInt8](count: count, repeatedValue: 0)
receiptContents.getBytes(&bytes, length:count * sizeof(UInt8))
//parsing
for index in 0...5
{
let value = Int(bytes[index])
println(value)
}
I get this output:
48
130
21
57
6
9
but if understand the ASN.1 format correctly, it's supposed to start with a value of 17 (set), then 3 bytes for the length (Int24?), then a value of 16 (first sequence), sequence length (1 byte), sequence type (1 byte), sequence payload, (repeat).
Other types like Int32, Int16 makes even less sense to me.
Not sure how to proceed here. Any suggestions?
From the outset, I suppose I should disclaim this by saying I'm not very familiar with many of the underlying technologies (Swift, OpenSSL, the Biometrics standards that I think you're working with).
That said, you're probably running afoul of BER's tagging rules. The Wiki article on X.690 has some introductory comments about how BER tags are constructed, but really you'll want to consult Annex A of X.690 for an example encoding and X.680 §8 for information about tagging.
A SET type can appear in several different forms; but in your case 49 = 0x31 = 0b00110001 = UNIVERSAL 17 (SET, constructed). Other forms may occur, but this is the only one that's explicitly identified as a SET from the tag itself: the specification may use a different tag for a SET type.
This question already has answers here:
How to sort an array of custom objects by property value in Swift
(20 answers)
Closed 7 years ago.
I am trying to sort an array of structure depending on its property.
Lets say I want to sort an array of NSViews by the x coordinate.
How can I achive this?
Its a very pretty solution for that, and its called Closure Expression Syntax.
What you need to do is:
let sortedArray = sorted(allViewsArray, { (p1: NSView, p2: NSView) -> Bool in
return p1.frame.origin.x < p2.frame.origin.x
})
This will sort the alLViewsArray from the biggest X coordinate to the smallest, and store it in sortedArary.
Note, you can simplify the syntax a little, which often helps with readability (focus is on what you’re doing rather than the syntax of the types etc):
let sortedArray = sorted(allViewsArray) {
$0.frame.origin.x < $1.frame.origin.x
}
Trailing closures can be outside the function call parens, resembling other block structures like if or while; you can skip the return if the closure expression is a single statement, and you can skip the function signature and use $0, $1 etc. for the argument names.
That last one is best used only when there are no more useful names to be had (e.g. p1 is no more descriptive than $0). If you do want to give them names, you can still skip the types:
let sortedArray = sorted(allViewsArray) { p1, p2 in
p1.frame.origin.x < p2.frame.origin.x
}
Swift is sometimes a little fragile when applying this syntax sugar so occasionally you’ll find it can’t be shortened quite as much as it ought, but it usually works.
Hello guys I'm new here and right now I'm learning Swift by coding some fancy algorithms, which comes to my mind while reading Apples Swift book.
I was trying to compress (automatically downcast) any IntegerType value.
Here is a little snippet of my Code which almost works fine except for one case:
switch signedValue
{
case Int64(Int8.min)...Int64(Int8.max): compressedValue = Int8(signedValue)
case (Int64(Int8.max) + 1)...Int64(UInt8.max): compressedValue = UInt8(signedValue)
case Int64(Int16.min)...Int64(Int16.max): compressedValue = Int16(signedValue)
case (Int64(Int16.max) + 1)...Int64(UInt16.max): compressedValue = UInt16(signedValue)
case Int64(Int32.min)...Int64(Int32.max): compressedValue = Int32(signedValue)
case (Int64(Int32.max) + 1)...Int64(UInt32.max): compressedValue = UInt32(signedValue)
case Int64(Int.min)...Int64(Int.max): compressedValue = Int(signedValue) // range bug #1 - workaround '..<'
default: compressedValue = signedValue
}
Assume signedValue is of Type Int64 and the input value is = 10_000_000_000.
This will lead to a runtime error (in Playground):
Execution was interrupted, reason: EXC_BAD_INSTRUCTION ...
Could anyone help me out to understand what exactly is happening here. There is an workaround for this problem. Instead of '...' I could use '..<' but this not how the range should be.
Unlike intervals (which have two flavours, half-open or closed), Range is only ever half-open. So when you write 1...5, the ...function increments the right-hand argument in order to create a half-open range 1..<6.
The consequence of this is you can’t have a range that spans the entire length of an integer type, since 1...Int.max will result in an attempt to increment Int.max, and an overflow error. You get a similar error with let s = "hello"; let r = s.startIndex...s.endIndex
All is not lost, however, since you shouldn’t be using ranges anyway, this is a job for ClosedInterval. Since the ... operator is used for both, and defaults to ranges (for overloading precedence reasons) you need to explicitly identify the type:
let i64interval: ClosedInterval = Int64(Int64.min)...Int64(Int64.max)
switch signedValue {
// etc
case i64interval: compressedValue = Int(signedValue)
default: compressedValue = signedValue
}
Look at the documentation for the Range Type. It has the following little nugget of information that I never noticed before:
if T has a maximal value, it can serve as an endIndex, but can never be contained in a Range.
T, in that quote, is the type of value in the Range. So if you have a Range of Ints, the max value of the Int cannot be contained in the Range.
That's why it works if you put the ..< in there, instead of ....
Good question, by the way...