Force an integer overflow?

So I'm using the chown C API (man 2 chown, Ubuntu 16.04, Swift 4.1). And the man page says the chown call has the following signature:

int chown(const char *pathname, uid_t owner, gid_t group);

Then in the man page description section it says:

If the owner or group is specified as -1, then that ID is not changed.

So, I have this function I'm trying to use to call into the chown C API:

public func change(owner uid: uid_t = -1, group gid: gid_t = -1) throws {
      guard chown(string, uid, gid) == 0 else {
          throw ChangeOwnershipError.getError()
      }
}

Which fails to compile with the following error message on the function declaration line:

integer literal '-1' overflows when stored into unsigned 'Builtin.Int32'

The uid_t/gid_t types are correctly being typecast as UInt32.

I also tried this, with the same error message though.
public func change(owner uid: uid_t? = nil, group gid: gid_t? = nil) throws {
>>    guard chown(string, uid ?? -1, gid ?? -1) == 0 else {
          throw ChangeOwnershipError.getError()
      }
}

I understand that -1 is not a valid unsigned integer and would cause an overflow. My frustration is that I can't literally follow the documentation, even though I realize I can technically just use UInt32.max for the same result.

Is there some way around this by overriding the integer literal inits for UInt32? or will the stdlib implementation just be called anyways?

You can use init(bitPattern:) to reinterpret between signed and unsigned integers:

public func change(owner uid: uid_t = uid_t(bitPattern: -1), group gid: gid_t = gid_t(bitPattern: -1)) throws {
      guard chown(string, uid, gid) == 0 else {
          throw ChangeOwnershipError.getError()
      }
}
2 Likes

Awesome thanks! That was exactly what I needed.

Just in case you're curious, several other ways to get the same value:

  1. 0 &- 1
  2. ~0
  3. uid_t.max
  4. uid_t(truncatingIfNeeded: -1)
2 Likes

Thanks, those are all useful as well!

uid_t.max can actually just be shortened to .max (since function parameters already have the type declaration).

I think .max is my favorite solution so far. It's only 4 chars and still rather easily understood.

1 Like