RSS and Atom feed reader

Hi,

For quite sometime now I've been working on a feed reader. It isn't anything special, but suits my needs. Here is a small demo video and here is a link to a test version ( 0.1 ). I've used it for more than a year now and don't plan to change much in the future. It's a test version because I changed/fixed/cleaned lots of things in the past few weeks and I'd like some testing before calling it "finished".

Any feedback would be appreciated.

I also have a question: I'm still using Windows 7, and when I tested the application on Windows 10, I was greeted by a message telling me that the application contains a trojan and wasn't able to launch the application. After a little search, it appears that it's common for Windows Defender AI/Cloud thing to mark every application as such and that the way around this is to submit the application to Microsoft on this page. Is that really the thing to do ? Is there another way around that ?

Edit: version 0.2


Edited by Simon Anciaux on Reason: Version 0.2
Hey I work in security, so regarding your last question I think yes you might have just gotten unlucky with Windows Defender. It's a simple application and using a combination of APIs which is maybe found in some malicious executables, so the machine learning or whatever probably triggered.
Looking at it myself, out of context it seems to be doing file deletion, input and clipboard collection, system enumeration etc., in combination with Internet access. And if you compiled it in an unusual way or whatever the 'algorithm' may hold that against you.
Thanks for the reply.

Halarious
And if you compiled it in an unusual way...


What do you mean by compiling in an unusual way ? I'm compiling from the command line with the following commands:

1
2
rc -nologo Y:\rss_reader\cbuild.rc
cl Y:\rss_reader\main.c Y:\rss_reader\cbuild.res -Fefeed.exe -nologo -GR- -EHa- -Oi -fp:fast -WX -W4 -wd4100 -wd4189 -wd4201 -wd4204 -wd4505 -wd4996 -wd4307 -FC -Fm -Zi -diagnostics:caret -diagnostics:column -Od -MTd -DCOMPILER_CL -DDEBUG -D_ASSERT -DWINDOWS -DTARGET_x64 -DLOG -link -INCREMENTAL:NO -opt:ref -subsystem:windows -entry:mainCRTStartup wininet.lib shell32.lib user32.lib OpenGL32.lib GDI32.lib Dwmapi.lib Shlwapi.lib Comdlg32.lib Ole32.lib


Is that considered unusual ?

When I looked into the issue there were people claiming that an empty main function could be marked as trojan, although I think they were talking about another anti-virus (if I remember correctly). I didn't check that (as I'm not often using Windows 10).

Halarious
...file deletion, input and clipboard collection, system enumeration etc., in combination with Internet access...


I'm doing all of that, using only Windows APIs. I sort of understand the idea that it looks bad without context, but... I'm just using the operating system. The worst thing was that Windows Defender didn't leave me the choice to run the application. Most of the time trying to launch it resulted in nothing happening, and on another computer it deleted the file directly.

Is the only solution to submit the program for review ? I assume the microsoft page will only take care of Windows Defender, so do I need to submit to other anti-virus vendors ?
By unusual I meant for example stripping the CRT, or it may indeed have to do with not having main; anything which is not that commonly done. But these are all guesses and don't really mean anything, just something which may contribute to some AI false labeling it as malware.

Also, your load config table seems to be invalid which may be "suspicious", but I don't know why that would be of the top of my head since you seem to be compiling it quite normally. Some info on it from the MSDN page:
https://docs.microsoft.com/en-us/...onfiguration-structure-image-only

Maybe also enabling /guard:cf and /SDL would somehow lend more legitimacy (both are currently disabled).

Other than that, I'm not sure you can do much which isn't playing the algorithm (e.g. dynamically loading some of the imports to trip machine learning models up). Packing it with something like UPX might be a hack which works, but better solutions usually unpack these so it might not have any impact, but who knows.


For personal use, you can add "Exclusions" in Windows Defender, folders which won't be scanned for malware. It should leave everything in exclusion folders alone.

Edited by Halarious on
I don't know much about PE headers, but I inspected 6 executables (with this tool, which I don't know so it might not be good) and 3 of them had a config table that was empty except for the Characteristics field, one also had the reserved field set and 2 had no config table at all. So it doesn't seem to be a problem.

Anyway, thanks for the help.

Edited by Simon Anciaux on

Version 0.2 changelog:

  • Fixed an issue with the html parser memory allocator.

Download feed 0.2


Edited by Simon Anciaux on Reason: Fixed link

Version 0.3 changelog:

  • Added support for youtube feeds.

Download feed 0.3

I don't really have a project for the visibility jam, but today I was changing some code in the feed reader while I was looking at performance, and ended up writing some small visualization.

One of my test case is displaying a "big" html page, and I was looking at how much time was spent looking up kerning information for codepoints. Turns out there was about a lot of calls to the kerning function, about 96000 (times 2 but it doesn't matter), so I looked up if a binary search would be faster than the current linear search for that particular function.

The perfs seemed similar in the two cases, with the binary search maybe a tiny bit faster (talking about 200 micro seconds so it doesn't matter). So I then decided to check if the new version of the function was producing the same result as the old one. I wrote this simple code:

data_t output = memory_get_virtual( mebioctet( 10 ), 0 );
    
for ( umm i = 0; i < set.codepoint_count; i++ ) {
	
	s32 codepoint = set.codepoints[ i ];
	codepoint_metrics_t* cm = font_get_codepoint_metrics( collection.fonts, codepoint );
	b32 out = false;
	
	for ( umm j = 0; j < set.codepoint_count; j++ ) {
		
		s32 kerning = font_get_kerning( collection.fonts, cm, set.codepoints[ j ] );
		
		if ( kerning ) {
			
			if ( !out ) {
				string_push_u64( &output, codepoint, 0, 0, 0 );
				memory_push_copy_l( &output, ":\n" );
				out = true;
			}
			
			memory_push_copy_l( &output, "    " );
			string_push_u64( &output, set.codepoints[ j ], 0, 0, 0 );
			memory_push_copy_l( &output, ", " );
			string_push_s64( &output, kerning, 0, 0, 0 );
			memory_push_copy_l( &output, "\n" );
		}
	}
}

file_write_entire( string_l( "kern_1.txt" ), output.bytes, output.used, true, &g_file_error );

Which produce this kind of result

33:
    8217, -100
    8221, -100
39:
    65, -100
    198, -100
44:
    8217, -210
    8221, -210
45:
    65, -50
    73, -30
    74, -100
    83, -20
    84, -150
    86, -50
    87, -50
    88, -80
    89, -140
    90, -30
    97, -20
    118, -40
    119, -20
    120, -50
    121, -40
    122, -40
    198, -50
    230, -20
46:
    44, -130
    45, -160
    173, -160
    8211, -120
    8212, -120
    8217, -210
    8221, -210
...

And they didn't produce the same result. The new version seemed to produce wrong values: most of the original output consist of negative values that are multiples of 10 and I wasn't seeing that in the new version.

So I tried to figure what was wrong and while the process wasn't interesting, it turned out that both version were wrong, and I had been using wrong kerning information for several years !

The codepoint_metrics_t struct contained the offset to use to reach the correct part of the kerning array for that codepoint. I never filled that offset after pushing things in the array, meaning all kerning queries started on the first element of the array (only the first codepoint metrics produced the correct value) and since the number of kerning entries was correct for each codepoint metrics, the search often didn't find the requested codepoint, and when it did, it was likely not the correct value.

After fixing the issue, I took a before and after screenshot and did a difference between the two to see the change. Here is what came up (opening the images in a new tab is a good idea):

Before (wrong) kerning_incorrect.png

After (correct) kerning_correct.png

Animated kerning_anim.gif

Difference kerning_difference.png

That's all for me.


Edited by Simon Anciaux on

Version 0.5 changelog

  • New ui system.
  • Improved basic html layout.
  • Improved log messages.
  • Added text filter in the feed list <CTRL + F>. Applies on the currently selected generations. Click [All] to filter on all feed and entries.
  • Bumped the maximun number of feed to 200.

Version 0.4 changelog

  • New xml parser.
  • Fixed an issues with line wrapping when a word doesn't fit on an empty line.
  • Fixed crashing when entry title is empty.
  • Fixed letter spacing and kerning.

Download

Version 0.6 changelog

  • Switched graphics API from OpenGL to DirectX 11.
  • Added tabs instead of "mode buttons".
  • Replaced some button labels with button icons.
  • Improved the help panel.
  • Made it easier to add youtube feed: you can just specify a channel id in the Add field.
  • Fixed enclosure link not always working.
  • Reworked log and error presentation. Still not great.
  • Fixed some potential layout issues.

Download Feed Reader 0.6