"EXC_BAD_ACCESS" occurs in CFNetworkExecuteProxyAutoConfigurationScript ()

I am trying to set up an HTTP proxy that can be used system-wide from an app. After some research, it looks like the CoreFoundation library's CFNetworkExecuteProxyAutoConfigurationScript() function can be used to configure the proxy.

(1) Is it possible to set the HTTP proxy available system-wide with CFNetworkExecuteProxyAutoConfigurationScript()?

(2) I tried the following source code but "EXC_BAD_ACCESS" occurs and the callback block is not called. Do you know what is the problem?


  • (void)startNextRequest

{ Request *request = _requests.firstObject; if (request == nil) { return; }

CFStreamClientContext context; memset(&context, 0, sizeof(CFStreamClientContext)); context.info = (__bridge void * _Null_unspecified)(self);

CFRunLoopSourceRef rls = CFNetworkExecuteProxyAutoConfigurationScript( (__bridge CFStringRef _Nonnull)(_script), (__bridge CFURLRef _Nonnull)(request.targetURL), (__bridge void *)^(PACResolver *client, CFArrayRef proxies, CFErrorRef error) { [client resolveDidFinishWithProxies:proxies error:error]; }, &context);

assert(_runLoopSource == nil); _runLoopSource = rls; CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); }

Environment:

Xcode 13.1 iPad 8th gen. iOS 14.0.1

Calling CFNetworkExecuteProxyAutoConfigurationScript is quite tricky. You can find a Swift example of how to do it in this post. I don’t have an Objective-C version handy.

I took a look at your code and worked out what the problem is. This snippet is not correct:

(__bridge void *)^(PACResolver *client, CFArrayRef proxies, CFErrorRef error) {
    …
}

I suspect you think that’ll create an anonymous function, but it does not. Rather, the block becomes an object which you then bridge to void *. When CFNetworkExecuteProxyAutoConfigurationScript tries to call that as a function, you crash.

To fix this declare a named standalone C function and pass that in to CFNetworkExecuteProxyAutoConfigurationScript. Here’s what that would look like:

static void MyCFProxyAutoConfigurationResultCallback(void *client, CFArrayRef proxyList, CFErrorRef __nullable error) {
    …
}

Two other things:

  • If you post a code snippet, add triple backquote delimiters so that it renders as code (or just click the Code Block button) rather than being interpreted as Markdown.

  • I generally recommend that you avoid using CFNetworkExecuteProxyAutoConfigurationScript and instead use our high-level APIs, Network framework and NSURLSession, which handle proxies automatically.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thanks for the advice. The build now passes. Thanks to eskimo for his polite response.

However, after running that code, I read the proxy settings by CFNetworkCopySystemProxySettings, but the proxy I set was not left. My goal is to set the proxy used when opening a URL in safari by my app.

Can't the CFNetworkExecuteProxyAutoConfigurationScript set a system-wide proxy?

I also tried the Swift example in this post that you gave me, with the same result.

My goal is to set the proxy used when opening a URL in safari by my app.

Can't the CFNetworkExecuteProxyAutoConfigurationScript set a system-wide proxy?

Hmmm, perhaps I’ve misunderstood but the above makes it sound like you’re trying to change the proxy settings system-wide. That is, your app sets a proxy and that proxy is used by other apps, including Safari. Is that right?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thank you for your comment.

That is, your app sets a proxy and that proxy is used by other apps, including Safari. Is that right?

That's right. Is there a way to achieve that?

Is there a way to achieve that?

No [1].

On iOS proxy configuration is under the control of the user (or the device manager in managed environments). There’s no API to change it.

Why are you trying to do this? What’s your end goal here?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] On iOS. The story is more nuanced on macOS.

Thank you for your comment.

Why are you trying to do this? What’s your end goal here?

My goal is to set the proxy used when opening a URL in safari by my app, in order for the user to skip network setup work.

 

There’s no API to change it.

I think configuration profile or manual setting is possible, but is there any other way to change the proxy automatically?

My goal is to set the proxy used when opening a URL in safari by my app, in order for the user to skip network setup work.

That’s not possible. Safari always uses the system proxy setup.

What would be nice here is a way to set up WKWebView to use a specific proxy. Many developers have asked for that but, alas, it’s not yet been implemented.

I think configuration profile or manual setting is possible, but is there any other way to change the proxy automatically?

How do you distribute your app? Is this a standard App Store app that ships to a wide range of users? Or something that typically runs in a managed environment.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thank you for your comment.

What would be nice here is a way to set up WKWebView to use a specific proxy. Many developers have asked for that but, alas, it’s not yet been implemented.

Thank you for your advice.I understood that there was no way.

 

How do you distribute your app? Is this a standard App Store app that ships to a wide range of users? Or something that typically runs in a managed environment.

It runs in a managed environment.

I will distribute it by MDM.

"EXC_BAD_ACCESS" occurs in CFNetworkExecuteProxyAutoConfigurationScript ()
 
 
Q