If you use the eloquence64 #eloquence addon for the #NVDA#screenreader, a critical security release is now available. This is a critical update! Please update as soon as possible.
If you use Eloquence64 on secure screens, after the update, you must IMMEDIATELY! go to NVDA's settings dialogue, select eloquence from the list box, and press the "copy helper to system config" button again.
It fixes the following issues: * fix: eloquence64 now clears its log file on start * Fix: in some cases, eloquence64 could write to its log file at 30 megs per second * fix: in some cases, eloquence64 created multiple temp files and directories that could not be removed * fix: in some cases, eloquence64 could unexpectedly leave a port open on the computer * fix: the port and key to communicate with eloquence could be intercepted by other processes running on the machine * fix: in rare cases, it could have been possible for other processes on the user's machine to cause the addon to load and run arbitrary Python code by causing it to deserialize an attacker supplied pickle. If the addon was running on a secure screen, this would mean instant privilege escalation. * fixed: crashing or frozen NVDA will no longer leave orphaned eloquence processes behind * fix: more reliable pause and break lengths * security hardening: switch to named pipes with DACL for IPC, ensuring no other process can use the 32-bit host
@draeand In my case, I need something fast and built in. It really is the best fit. The issue here was using tcp for ipc. That was a poor decision that just happened rather than being intentionally considered.
@fastfinge I mean, you could use flat buffers or similar. That’s not built-in perhaps but it also doesn’t come with the risk of arbitrary RCE vulnerabilities in your code if you choose to use IPC mechanisms like this or to allow third parties to interact with serialized data. The downside is it’s an external dependency, but it’s insanely fast. Pickle is something you should only use if you have absolute control over the data that you unpickle.
@draeand Yes, and that was the problem. Third parties should not have been able to interact with the process that unpickles data. They could because I allowed things to happen as the code took shape over the past six years, and failed to review third partie PR's closely enough, rather than creating an intentional design for it. It then bit me when I forgot to correctly clean up the process that was listening to the TCP socket as part of other changes. The correct answer in this case was to move to named pipes, with process and group ased ACL, not dump pickle.
@draeand The ultimate solution is to rewrite the 32-bit eloquence host in something like rust, the way eloquence64RS does. But I don't speak or understand rust, so I'm not confident either writing it myself, or reviewing and sanity checking an AI generated rust host. Plus, NVDA itself, and the addon portion, are in Python. And I prefer to only require contributors (and me) to deal with a single programming language. Based on that round of bug-fixing, I'm already completely incapable of doing an adequate job. More complexity will not help me.
@fastfinge@draeand I get why you made the decisions you did, I really do. But I genuinely wonder whether rewriting the host in C# wouldn't be the right call for you. Yes, the contributors issue, but I'd ask the most regular ones if they'd be happy with such a move - you genuinely get a performance uplift doing it, for instance.
@nick@draeand I wouldn't, though. First the dotnet runtime would now be required, and would be a huge memory suck. Second the only lag Python brings is the first startup/JIT compile. Once that happens, it's just reading data off a pipe and passing it to eloquence. Getting rid of TCP saved me somewhere between 40 and 60 nanoseconds. But that's well below the limit of human perceivability. And generating NVDA indexes etc still happens in Python, because that's what NVDA uses. So a low level language just can't save anything here. The reason your rust driver feels more accurate is because you're playing back chunks sooner, and thus making indexing slightly less accurate in return. That's not a tradeoff I'd want to make. If I did, it could just as easily be made in Python.
@fastfinge@draeand Ah, I forgot about the .net runtime, so you'd get literally no RAM savings. Rust does get you those RAM savings, but I'll stand correct and admit that may be all it's giving me. Obviously, the main difference between our addons is that I'm willing to make that tradeoff in the name of responsiveness where you aren't, and that might be a big enough difference in daily use for both addons to need to exist.
@fastfinge@draeand As it happens, I do have one question. Have you tried the OpenEVV addon with Unspoken? Is it still early? Because that thing is just as quick as 64RS.
@nick@draeand It is. When the OpenEVV guys fix all the IBM introduced bugs, I intend to switch over to using there dlls, and just build those into the eloquence64 addon and get rid of IPC. Not doing IPC at all will get us a noticeable 40ms or so.
@fastfinge@nick@draeand I'm surprised that IPC adds double-digit milliseconds. The last time I measured IPC on Windows (specifically for the UI Automation API), inside a VM on a much older machine about 10 years ago, the round trip times were in the range of a few hundred microseconds.
@matt@nick@draeand In the real world, most machines have endpoint security and virus scanning and things that watch IPC carefully, and slow everything down. Especially when you're using TCP. Switching to pipes will probably bring some speedups for some folks, depending.
@fastfinge@matt@nick@draeand Are you saying that endpoint security adds 40 or more milliseconds of latency to each TCP packet? It seems a bit hard to believe, but Windows is the only OS on which the close syscall is slow and must often be relegated to a background thread, so what do I know. Or are you doing something interesting, like making a new connection on every utterance?
@miki@matt@nick@draeand Depends on the security software and the environment and the app. For an unsigned executable in an untrusted environment, running as admin, sometimes it can, yes. Of course this is not usually the case, so that kind of lag isn't going to hit most people, running most apps.
@matt@nick@draeand Now that you've got me curious, there are two places I can save. First, building the 32-bit hoast as onedir instead of onefile. Saves 1.5 seconds on first start. Second, I can shorten the audio buffer and save about 40 ms per speech. But that'll need a lot of testing to make sure it doesn't introduce underruns on slow systems.
@nick@draeand Just did some quick benchmarking. Based on the hotpath, a rewrite away from python could save as much as, get ready, 0.0005% of processing time.
@fastfinge@draeand LOL. ...Which honestly just means my experiment wasn't worth doing, except only insofar as it makes my experience using Windows on a Macbook Neo better as that's a very constrained environment. Honestly, when OpenEVV is actually ready, I'm getting out.
@nick@draeand The only other thing it gives you is some disc savings. The 32-bit host does bundle all of Python with it, and unpacks it into a temp directory whenever it runs, then cleans it up when it exits. Well, should clean it up when it exits. It does, now, clean it up when it exits. Sigh.